从前天学习GPS定位开始,这两天断断续续都在学习Android的三种基本定位方式。
1.GPS定位(基本Android机上都会有,缺点是必须在空旷的地方才有用)
2.网络定位(NetWork,这个很多手机上没有这个功能,比如我的联想机就没有这个功能)
4.基站定位(获取基站信息,然后向谷歌发送解析要求,解析地址)
在编写代码时,遇到了很多问题,大多数时间都是花费在一些不太注意的小问题上了,而且最后基站定位也还是有BUG(Http post不会执行)
遇到的问题:
1.权限没有添加,定位时需要的权限
1.1:<uses-permission android:name="android.permission.INTERNET" />(网络连接)
1.2:<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />(基站定位时需要的权限)
1.3:<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> (网络定位需要的权限)
1.4<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>(GPS精确定位时需要的权限)
2.GPS定位和网络定位时,没有添加监听函数:requestLocationUpdates().
正确的做法应该是在 onResume里面注册监听函数GPS位置监听和GPS状态监听(NetWork位置监听),然后在onPause()里面取消对应的监听
3.抛出错误:ERROR/LocationManagerService(1236): java.lang.IllegalArgumentException: provider=network(这是由于手机上不支持NetWork定位功能,没办法)
4.基站定位:程序执行到HttpResponse resp = client.execute(post)时会自动抛出错误,而且Catch捕获的错误是null.
解决方法1:在主线程里面使用了耗时操作,Android4.0以后不被允许,加上一下代码即可解决:
(但是这个方法会将程序一直卡着,虽然没出错,但是我的手机运行这个程序后直接就死掉了)
/**解决4.0中不能进行网络操作要求
* 暴力方法
* 其实最好是另外单独使用一个线程,完了后告诉主线程
if (Build.VERSION.SDK_INT >= 11) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads ().detectDiskWrites().detectNetwork().penaltyLog().build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedClosableObjects().penaltyLog().penaltyDeath().build());
}
*/
解决方法2(Thread+Handler):重新开一个线程MyThread,然后在MyThread里面执行耗时操作,将结果通知MyHandler,其中创建MyHandler时,将MyHandler与主线程的Looper绑定,所以在子线程MyThread里面通过MyHandler即可发送消息给主线程,主线程只需要重写handleMessage(Message msg)函数即可接收相应的消息并进行处理。这是异步线程交互的一种最常用的方式。
***但是问题来了:在我用了(Thread+Handler)的方式后,程序执行到HttpResponse resp = client.execute(post)时还是会自动抛出错误,而且捕获不到错误(如果尝试输出错误信息又会抛出新的错误(java.lang.NullPointerException:println needs a message),因为捕获到的是null)。目前还不知道为什么会这样。
一些小结:
1.在是线程间传送消息时,用到了bundle,关于bundle的使用
1.1bundle可以直接设置一些常用的类型,String,int,boolean等
1.2当需要自定义类型Object时,需要将Object类序列化(可以Serializable也可以Parcelable,其中实现Parcelable时需要重写几个方法),需要注意的时,父类序列化时,子类也是默认序列化的。
2.关于Toast的显示,Toast是依附于Activity的,所以在Activity中的子线程里面最好不要使用Toast,如果需要显示,则有下列几种解决方法
2.1:Looper.prepare(); Toast显示内容; Looper.loop();(注意,Toast显示一定要用 .show())
2.2:使用线程见的通信方式,子线程通过MyHandle发送消息给主线程,然后在主线程里面选择对应的消息类型然后进行相应的处理。
3.子线程访问主线程中的UI界面,这里介绍两种方法:
3.1:通过MyHandler.post(new Thread())其实是只调用线程的run()方法,然不是调用start()方法来启动一个新线程,其本质是在主线程里面调用了另外一个线程的run()方法,而不是新开一个线程,所以还是不能做耗时操作。
3.2new Thread(new Runnable()).start(),新开一个线程后,通过MyHandler来给主线程发送消息,主线程发送消息后在进行相应的处理,新开了一个线程,异步执行,所以可以做耗时操作。
4.在创建Activity对应的Handler时&#