在手机中最经常使用的定位技术是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能够作到重启服务。二者有一个共同点,就是都能修改锁屏内容。可能要作到流氓就必须抱大腿,跟特权的系统服务绑定在一块儿。