Android性能优化之被动定位

位置在这个LBS与SNS的时代显得特别重要,Android获取移动设备位置的功能也成为大多数App的标配。

最常用的定位方式有以下几种:

1.GPS

2.网络(包括基站、WIFI)

3.被动定位

以上3种方式中,GPS定位经度最高,水平精度可达10米左右,虽然GPS定位精度高,但是这种方式是最费电的,同时定位的时间也比较长,尤其是在GPS信号不好的情况下。甚至有时候,如果你在室内,那么GPS定位只是徒劳而已。网络定位速度较快,依赖于网络状况良好与否。其实很多情况下,我们都是同时使用多种定位方式,像百度地图的定位SDK和高德地图的定位SDK都提供了网络和GPS混合定位的方式。多种定位方式的混合定位可以减少定位时间,但是对电量的消耗却没有帮助。

再来看被动定位,被动定位我们一般用的比较少,它是在API=8才加入的,顾名思义,这种方式不是主动去请求位置信息,而是被动的接收位置更新,因此这种方式是最省电的。具体来说,我们的App如果想知道位置信息,只需要开启一个位置监听即可,然后就等待其他应用或服务主动发出位置请求,我们的App可以和主动发起为之请求的组件同时接收更新。很明显被动定位的方式有着严重的局限性,因为我们的定位依赖于其他应用,那么则无法控制定位的实时性,如果在一段时间内没有任何其他应用主动请求位置,那么被动定位则不会收到位置更新,只能继续等待;如果我们急于获取位置,那么这种方式就不适用。有时候觉得这种方式有点自私,因为它自己不怎么耗电,而却把定位消耗的电量算到其他应用的头上了,有点坐享其成的感觉,既然Android API提供了这种方式,应该会在某个合适的时候有它的特定用途吧。

有时候在特定的需求下,宁可牺牲电量来频繁请求位置;也有的为了节省电量而使用省电的定位方法和限制定位请求次数。Android还提供了Criteria对象,通过设置各种条件来筛选符合要求的定位服务,这些限制条件包括精度、耗电等。

一般来说,可以同时使用网络定位和被动定位方式,网络定位方式比GPS方式省电且速度较快,使用被动定位方式可以接收GPS的精确的位置信息。

因为被动定位用的比较少,所以提供一个被动定位的测试demo,就一个Activity,布局文件很简单,只有一个textview(显示定位结果)和一个button(启动被动定位)。Activity的代码如下:

package com.andy.passivelocation;

import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {
	
	private final String TAG = "MainActivity";
	private TextView mTextView;
	private Button mButton;
	private Handler mHandler;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		mTextView = (TextView) findViewById(R.id.location);
		mButton = (Button) findViewById(R.id.locationBtn);
		
		mButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				mButton.setText("被动定位中……");
				requestPassiveLocationUpdates();
			}
		});
		
		mHandler = new Handler() {
			@Override
			public void dispatchMessage(Message msg) {
				// TODO Auto-generated method stub
				super.dispatchMessage(msg);
				Location location = (Location) msg.obj;
				switch (msg.what) {
				case 1:	
					if (location != null) {
						mTextView.setText("GPS:" + location.getLatitude() + "," + location.getLongitude());
						mButton.setText("Passive Location");
					}			
					break;
				case 2:
					if (location != null) {
						mTextView.setText("NetWork:" + location.getLatitude() + "," + location.getLongitude());
						mButton.setText("Passive Location");
					}		
					break;
				default:
					break;
				}
			}
		};
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	
	public void requestPassiveLocationUpdates() {
		LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		LocationListener listener = new LocationListener() {
			
			@Override
			public void onStatusChanged(String provider, int status, Bundle extras) {
				// TODO Auto-generated method stub
				Log.e(TAG, "[Passive]" + provider + "onStatusChanged");
			}
			
			@Override
			public void onProviderEnabled(String provider) {
				// TODO Auto-generated method stub
				Log.e(TAG, "[Passive]" + provider + "onProviderEnabled");
			}
			
			@Override
			public void onProviderDisabled(String provider) {
				// TODO Auto-generated method stub
				Log.e(TAG, "[Passive]" + provider + "onProviderDisabled");
			}
			
			@Override
			public void onLocationChanged(Location location) {
				// TODO Auto-generated method stub
				Log.e(TAG, "[Passive]-onLocationChanged");
				Message msg = new Message();				
				// GPS
				if (LocationManager.GPS_PROVIDER.equals(location.getProvider())) {
					msg.what = 1;
					msg.obj = location;
					mHandler.sendMessage(msg);
				} else if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) {
					// 网络
					msg.what = 2;
					msg.obj = location;
					mHandler.sendMessage(msg);
				}
			}
		};
		
		// 采用被动定位,为了省电
		manager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER,
				5000, 100, listener);
	}
	
}

点击按钮后,就开始了被动定位的监听,然后打开Google Map一下,Google Map会触发定位请求,当得到位置后,demo中的被动定位也会接收到该位置信息(可以判断是GPS定位结果还是网络定位结果,详见代码注释)。我在屋内测试,因此被动定位方式只能拿到网络定位结果,截图如下:

Android性能优化之被动定位_第1张图片


你可能感兴趣的:(android,GPS定位,网络定位,被动定位)