在手機中最經常使用的定位技術是GPS。
可是國內的應用並不能直接獲取真實的地理信息。
火星座標系統
各個座標系的介紹html
直接使用高德的SDK能夠省去很多麻煩。可是在使用SDK的時候須要key store。java
文檔很清楚高德SDK文檔,經過簡單的設置便可獲取須要的GPS信息。
可是要作到長時間監聽,還須要AlarmManager來保持CPU的工做。android
主要有4個步驟:git
class GpsService : Service() { private var mLocationClient: AMapLocationClient? = null //聲明定位回調監聽器 private var mLocationListener: AMapLocationListener = AMapLocationListener { amapLocation -> if (amapLocation != null) { if (amapLocation.errorCode == 0) { //解析定位結果 val latitude = amapLocation.latitude;//獲取緯度 val longitude = amapLocation.longitude;//獲取經度 PostDataTask().execute(Pair(latitude,longitude)) Log.i("location","acc : ${amapLocation.accuracy}") Log.i("location", "altitude : ${amapLocation.altitude}") } else Log.w("location","error code: ${amapLocation.errorInfo}") } } override fun onCreate() { mLocationClient = AMapLocationClient(applicationContext) //設置定位回調監聽 mLocationClient!!.setLocationListener(mLocationListener) val option = AMapLocationClientOption() /** * 設置定位場景,目前支持三種場景(簽到、出行、運動,默認無場景) */ option.locationPurpose = AMapLocationClientOption.AMapLocationPurpose.Transport option.locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy //啓動定位 mLocationClient!!.startLocation() } }
安卓不能直接使用MySQL。既然用了高德的服務,乾脆存儲也使用雲存儲。它提供了幾個十分方便的API。api
在安卓中不能再主線程中調用Http請求。須要TaskAync來輔助完成一次請求。微信
private class PostDataTask : AsyncTask<Pair<Double, Double>, Int, Boolean>() { override fun doInBackground(vararg args: Pair<Double, Double>): Boolean { for (arg in args) { val longitude = arg.first;//獲取緯度 val latitude= arg.second;//獲取經度 val now = System.currentTimeMillis() / 1000 val params =getDataString(mapOf( "key" to "2ad3b7f65c549d9155b7325c2d2c13b4", "tableid" to "5a80175d2376c17f0129f54c", "data" to " {\"_name\":\"$now\",\"_location\":\"$latitude,$longitude\" }")) Log.d("location",params) var url = URL("http://yuntuapi.amap.com/datamanage/data/create") val urlConnection = url.openConnection() as HttpURLConnection urlConnection.instanceFollowRedirects = false; urlConnection.doOutput = true urlConnection.requestMethod = "POST"; urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); urlConnection.setRequestProperty("charset", "utf-8"); urlConnection.setRequestProperty("Content-Length", Integer.toString(params.length)); urlConnection.useCaches = false; try { DataOutputStream(urlConnection.outputStream).write((params).toByteArray()) urlConnection.connect() if (urlConnection.responseCode in 200..299) { val br = (InputStreamReader(urlConnection.inputStream).readText()) Log.i("response", br) } } catch (e: java.io.IOException) { e.printStackTrace() } urlConnection.disconnect() } return true; } private fun getDataString(params: Map<String, String>): String { val result = StringBuilder() var first = true for (entry in params.keys) { if (first) first = false; else result.append("&"); result.append(URLEncoder.encode(entry, "UTF-8")); result.append("="); result.append(URLEncoder.encode(params[entry], "UTF-8")); } return result.toString(); } }
在使用該接口的時候,出現一個錯誤:app
{ "info": "參數缺失或格式非法", "infocode": "30001", "status": 0 }
開始還覺得是urlencode的不對,後來各類尋找也沒發現問題。最終發現是因爲經緯度的順序寫錯了,不支持地區就算了,返回這麼一個信息很頭疼啊。ide
其實這段代碼很是簡單,在啓動service的時候建立一個alarm,而後在alarm的接收器裏再次啓動service。從而達到不被關閉的效果。ui
//service 類中 override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { Log.i(TAG, "onStartCommand() executed") //Toast.makeText(this, "onStartCommand", Toast.LENGTH_SHORT).show(); val manager = getSystemService(Context.ALARM_SERVICE) as AlarmManager val alarmTime = 20 * 1000 // 定時10s val triggerAtTime = SystemClock.elapsedRealtime() + alarmTime val i = Intent(this, AlarmReceiver::class.java) val pi = PendingIntent.getBroadcast(this, 0, i, 0) manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi) return super.onStartCommand(intent, Service.START_FLAG_REDELIVERY, startId) }
Reciverthis
public class AlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Log.i("alarm","trigger alarm"); Intent i = new Intent(context, GpsService.class); context.startService(i); } }
public class BootBroadcastReceiver extends BroadcastReceiver { static final String ACTION = "android.intent.action.BOOT_COMPLETED"; @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(ACTION)) { Intent mainActivityIntent = new Intent(context, GpsService.class); // 要啓動的Activity mainActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(mainActivityIntent); } } }
流氓軟件的必備技能。但仍是有時候須要這麼一個東西。好比個人應用是一個定製化的軟件。這個時候整個系統都應該圍繞個人APP去工做。好比一個基於安卓的機器人系統。在空閒的時候容許用戶打開別的應用玩玩遊戲什麼的,可是個人後臺系統必需要時刻保持工做狀態。
試了裏面的幾種辦法,最後仍是沒有在個人魅藍2,yunOS 3.1.6上達到開機啓動加後臺常駐。果真仍是大廠技術高。我手機裏的高德、微信、金山詞霸、cortana都作到了。囧。可是除了cortana其他的都是2個進程在跑。微信和高德的是能夠被殺掉,並不會重啓。而金山詞霸、cortana能夠作到重啓服務。二者有一個共同點,就是都能修改鎖屏內容。可能要作到流氓就必須抱大腿,跟特權的系統服務綁定在一塊兒。