0%

android 地雷筆記

 
vim

最近被抓來寫 android 程式 , 順便筆記下遇到的問題 , 不然久了又忘了

解決訪問 web api 用 http 時噴 permitted by network security policy

參考這老外
res 資料夾底下新增 network_security_config.xml

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>

接著 AndroidMainfest.xmlapplication 標籤加入這段就搞定 , 記得網路權限也要開 , android 拿權限真是麻煩的概念

1
2
3
4
5
6
7
8
9
<!--使用網路權限-->
<uses-permission android:name="android.permission.INTERNET" />

<application
android:networkSecurityConfig="@xml/network_security_config"
android:usesCleartextTraffic="true"

<!-- 略... -->
</application>

exposed 筆記

參考這篇大神教學
因為是用 sql server , 本來想說可以用 localdb 不過微軟自己好像不支援 , 需要用 localdb 可以看看這篇
gradle.kts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
val exposedVersion: String by project
dependencies {
testImplementation(kotlin("test-junit"))

implementation("org.jetbrains.exposed:exposed-core:$exposedVersion")
implementation("org.jetbrains.exposed:exposed-dao:$exposedVersion")
implementation("org.jetbrains.exposed:exposed-jdbc:$exposedVersion")


// https://mvnrepository.com/artifact/com.microsoft.sqlserver/mssql-jdbc
implementation("com.microsoft.sqlserver:mssql-jdbc:9.4.1.jre8")

implementation("org.slf4j:slf4j-api:1.7.32")
implementation("org.slf4j:slf4j-log4j12:1.7.32")
}

接著這邊跟 entity framework code first 差不多 , 都要先定義 mapping 的物件
設定資料表 XY => 資料表名稱 , 因為是用 bigint 所以用 LongIdTable
primary key => XYID

1
2
3
4
object XYTable : LongIdTable("XY", "XYID") {
var x = decimal("X", 11, 8)
var y = decimal("Y" , 11 , 8)
}

定義 DAO 類別 , 這裡有個雷半天的地方 , 用 by 不能用 = 等號

1
2
3
4
5
6
7
class XY(id: EntityID<Long>) : LongEntity(id) {
companion object : LongEntityClass<XY>(XYTable)

var xyId by XYTable.id
var x by XYTable.x
var y by XYTable.y
}

撈 web api 筆記

build.gradle 先安裝套件 okhttpGSON

1
2
3
4
5
//ok http
implementation("com.squareup.okhttp3:okhttp:4.9.0")

//GSON
implementation 'com.google.code.gson:gson:2.8.6'

先打網址看看回啥格式 , 然後建立 data class , 這邊跟 c# 的 JsonPropertyName 類似 , 不過叫做 SerializedName 來設定 json 的欄位名稱

1
2
3
4
5
6
7
8
9
data class XY(
@SerializedName("XYID")
val XYID: Long,

@SerializedName("X")
val X:Double,

@SerializedName("Y")
val Y:Double

因為是撈 web api 的資料 , 時間格式會像這樣 2018-12-26T11:21:13 需要在 gson 設定 format , 沒設定的話會噴 No time zone indicator 要特別注意

1
val gson = GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss").create()

整個 function 會長這樣 , 另外要直接在 android 上面用的話 , 一定要用非同步的 enqueue , 不然也會噴 error

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private fun getData() {
val url = "http://yourip/api/xy/123"
val client = OkHttpClient().newBuilder().build();
val request = Request.Builder().url(url).get().build()
val call = client.newCall(request)
call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.e("MSG", "onFailure $e")
}

override fun onResponse(call: Call, response: Response) {
val json = response.body?.string()

//這句沒設定的話會噴 No time zone indicator 特別注意
val gson = GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss").create()
val listType = object : TypeToken<List<XY>>() {}.type
val xyList = gson.fromJson<List<XY>>(json, listType)
for (xy in xyList) {
Log.d("MSG", "lon: ${xy.X} lat: ${xy.Y}")
}

}
})
}

接著塞資料看看 , 因為對 android 沒啥經驗 , 他這個 Log.d 的第一個參數 tag 滿有趣的 , 可以在 Logcat 幫你用來篩選想看的資訊

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
private fun postData() {
val url = http://yourip/api/xy/add"
val client = OkHttpClient().newBuilder().build();

//val now = Calendar.getInstance().time
val xy = XY(
XYID = 0,
x = 123,
y = 45
)

val point = Gson().toJson(xy)

val body = point.toRequestBody("application/json".toMediaTypeOrNull());
val request = Request.Builder()
.url(url)
.post(body)
.build();

val call = client.newCall(request);
call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.e("your tag", "onFailure $e")
}

override fun onResponse(call: Call, response: Response) {
val resp = response.body?.string()
Log.d("your tag", "onResponse $resp")
}
})

}

GPS 定時取得經緯度

這個比想像中還不直覺 , 因為對 android 比較不熟 , 一開始以為用 background service 可以抓資料
後來搞了半天是要用 foreground service 可以參考這個老外的文章
source code 下載
google 官方 java 的example
中文資料可以參考這篇

關閉