BroadcastRecevier 및 Service로 APP-GPS 데이터 수집 서비스 시작

11333 단어 androidsqliteLBSgps
먼저 GPS 데이터 포지셔닝을 수집하는 방식은 GPS 위성 포지셔닝, 와이파이 포지셔닝, 기지국 포지셔닝, AGPS 포지셔닝이다.GPS 적용은 LBS 업계 소프트웨어에서 핵심으로 꼽힌다.
몇 가지 포지셔닝 방식 설명
(1) 안드로이드 GPS: GPS 하드웨어 지원이 필요하고 위성과 직접 상호작용을 해서 현재의 경위도를 얻을 수 있다. 이런 방식은 핸드폰으로 GPS 모듈을 지원해야 한다(현재 대부분의 스마트폰이 있을 것이다).GPS 방식을 통해 정확도가 가장 높지만 단점도 뚜렷하다. 1. 전기 소모가 비교적 크다.2, 대부분의 사용자가 기본적으로 GPS 모듈을 켜지 않습니다.3, GPS 모듈을 시작하여 첫 번째 포지셔닝 데이터를 얻는 데 비교적 긴 시간이 걸릴 수 있다.4, 실내는 거의 사용할 수 없습니다.이 중 단점 2, 3은 모두 치명적이다.GPS는 위성통신의 통로를 걸어서 네트워크 연결 없이도 사용할 수 있다는 점을 지적해야 한다.
(2) 안드로이드 와이파이 포지셔닝: 고정된 와이파이 맥 주소에 따라 수집된 와이파이 핫스팟의 위치를 통해 네트워크에 있는 포지셔닝 서비스에 액세스하여 경위도 좌표를 얻는다.기지국 포지셔닝과 사실상 네트워크를 사용해야 하기 때문에 안드로이드에서도 네트워크 방식이라고 통칭한다.
(3) 안드로이드 기지국 포지셔닝: 안드로이드 기지국 포지셔닝은 기지국/WIFI 포지셔닝의 원리를 이해하기만 하면 기지국/WIFI 포지셔닝을 스스로 실현하는 것은 사실 어렵지 않다.터미널 포지셔닝은 일반적으로 몇 가지가 있는데 첫 번째는 휴대전화 부근의 세 개의 터미널을 이용하여 삼각 포지셔닝을 한다. 각 터미널의 위치가 고정되어 있기 때문에 전자파를 이용하여 이 세 개의 터미널 사이를 회전하는 데 필요한 시간을 이용하여 휴대전화가 있는 좌표를 계산한다.두 번째는 가장 가까운 기지국 정보를 얻는 것이다. 기지국 id,location area code,mobile country code,mobile network code와 신호 강도를 포함하여 이 데이터를 구글의 포지셔닝 웹 서비스에 보내면 현재 위치정보를 얻을 수 있다. 오차는 보통 수십 미터에서 수백 미터 이내이다.
(4) AGPS 포지셔닝: AGPS(AssistedGPS: 보조 글로벌 위성 포지셔닝 시스템)는 GSM이나 GPRS와 전통 위성 포지셔닝을 결합하여 기지국에서 보조 위성 정보를 대신 전송하여 GPS칩을 이용하여 위성 신호를 얻는 지연 시간을 줄이고 가려진 실내도 기지국 신호를 빌려 보완하여 GPS칩이 위성에 대한 의존도를 줄일 수 있다.순수 GPS, 기지대 삼각 포지셔닝과 비교하면 AGPS는 범위가 더욱 넓고 전기를 절약하며 속도가 빠른 포지셔닝 서비스를 제공할 수 있다. 이상적인 오차 범위는 10미터 이내이다. 일본과 미국은 AGPS를 LBS 서비스(Location Based Service, 위치 기반 서비스)에 성숙하게 운용했다.AGPS 기술은 네트워크 기지국 정보와 GPS 정보를 결합시켜 모바일 플랫폼을 포지셔닝하는 기술로 GSM/GPRS, WCDMA와 CDMA2000 네트워크에서 사용할 수 있다.이 기술은 휴대전화 안에 GPS 수신기 모듈을 추가하고 휴대전화 안테나를 개조하는 동시에 모바일 네트워크에 위치 서버, 차분 GPS 기준역 등 설비를 가설해야 한다.AGPS 솔루션의 장점은 주로 위치 정밀도에 나타난다. 실외 등 광활한 지역에서 그 정밀도는 정상적인 GPS 작업 환경에서 10미터 정도에 달할 수 있고 현재 위치 정밀도가 가장 높은 위치 정밀도 기술이라고 할 수 있다.이 기술의 또 다른 장점은 GPS 신호를 처음 포획하는 시간은 일반적으로 몇 초밖에 걸리지 않으며 GPS의 첫 포획 시간보다 2~3분 정도 걸릴 수 있다는 것이다.
요약하면 가장 좋은 방안은 AGPS 포지셔닝이다. 왜냐하면 시간을 절약하고 (포지셔닝 시간이 빠르기 때문에) 전기를 절약하며 정밀도가 높고 수용도가 높기 때문이다.  
GPS 데이터 수집 논리적 구상 실현
(1) GPS 데이터의 현지화를 실현한다. SQLite를 사용하여 일정한 시간 주파수(일반 10s, 15s, 20s, 30s 심지어 더 크고 응용 데이터의 양에 따라 정할 수 있다. 보통 같은 시간에 채집하는 지점이 많을수록 이 시간 GPS 장치가 이동하는 궤적을 설명하기 쉽다)를 이용하여 GPS를 채집하여 로컬 SQLite 데이터베이스에 저장한다.
(2) GPS 데이터의 정시 업로드를 실현한다. 30분 간격으로 서버에 정기적으로 스레드(이동 스레드를 사용)를 던지고 로컬 데이터를 먼 서버로 동기화한다.
(3) 가입 서비스 및 APP 백그라운드: BroadcastReceiver를 사용하여 로컬 서비스(데이터 수집)와 원격 서비스(데이터 업로드)를 등록할 수 있다.
기능 요구 사항 충족
Local-Service 만들기
로컬 GPS 데이터 수집 서비스, SystemLocal Service.java
package com.boonya.wtms.service;

import com.boonya.wtms.domain.GPSLocation;
import com.boonya.wtms.utils.Constant;
import com.boonya.wtms.utils.DateParser;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;

public class SystemLocalService extends Service
{

	static LocationManager loctionManager;

	static String provider;

	private GPSLocationService gpsLocationService;

	Context tag = SystemLocalService.this;

	@Override
	public void onCreate()
	{
		super.onCreate();

		//   GPS       
		gpsLocationService = new GPSLocationService(tag);

	}

	@Override
	public IBinder onBind(Intent arg0)
	{
		return null;
	}

	//      
	@Override
	@Deprecated
	public void onStart(Intent intent, int startId)
	{
		//   GPS  
		initGPSLocationListener();
		super.onStart(intent, startId);
	}

	@Override
	public void onDestroy()
	{//    onDestroy  
		loctionManager.removeUpdates(locationListener);
		super.onDestroy();
	}

	private final LocationListener locationListener = new LocationListener()
	{

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras)
		{

		}

		@Override
		public void onProviderEnabled(String provider)
		{

		}

		@Override
		public void onProviderDisabled(String provider)
		{

		}

		//         

		@Override
		public void onLocationChanged(Location location)
		{
			if (location != null)
			{
				Thread thread = new Thread(new DoCollectThread(location));
				thread.start();
			}

		}

	};

	/**
	 *    GPS    
	 */
	protected void initGPSLocationListener()
	{

		String contextService = Context.LOCATION_SERVICE;

		//       ,  LocationManager  

		loctionManager = (LocationManager) getSystemService(contextService);

		// 3.        ,       ,      ,            ,           ,     
		//              ,              。

		// a.   GPS         (          )

		// String provider = LocationManager.GPS_PROVIDER;

		// Location location = loctionManager.getLastKnownLocation(provider);

		// b.       ,                 ,    

		Criteria criteria = new Criteria();

		criteria.setAccuracy(Criteria.ACCURACY_FINE);//    

		criteria.setAltitudeRequired(true);//     

		criteria.setBearingRequired(true);//     

		criteria.setSpeedRequired(true); //     

		criteria.setCostAllowed(true);//      

		criteria.setPowerRequirement(Criteria.POWER_LOW);//    

		//           ,            

		provider = loctionManager.getBestProvider(criteria, true);
		//            
		// Location location = loctionManager.getLastKnownLocation(provider);

		//           TextView ,  :

		//        

		//       ,2   ,  10   
		loctionManager.requestLocationUpdates(provider, Constant.GPS_COLLECT_TIME, Constant.GPS_COLLECT_DISTANCE, locationListener);

	}

	/**
	 *   GPS       SQLite
	 * 
	 * @author boonya
	 * 
	 * @having-line---------------------------------------------------------
	 * @filename SystemLocalService.java
	 * @function TODO
	 * @start-at 2014-12-11,  4:47:14
	 * @having-line---------------------------------------------------------
	 */
	class DoCollectThread implements Runnable
	{
		Location location;

		public DoCollectThread(Location location)
		{
			this.location = location;
		}

		@Override
		public void run()
		{
			GPSLocation gpsLocation = new GPSLocation(-1, location.getLatitude(), location.getLongitude(), location.getAltitude(), location.getBearing(), location.getSpeed(), DateParser.getSystemDateStr());

			gpsLocationService.saveToLocal(gpsLocation);

		}

	}

}

Remote-Service 생성
로컬 작업을 서버 서비스, SystemRemote Service에 동기화합니다.java
package com.boonya.wtms.service;

import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import com.boonya.wtms.domain.GPSLocation;
import com.boonya.wtms.utils.Constant;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;

public class SystemRemoteService extends Service
{
	Context tag = SystemRemoteService.this;

	private GPSLocationService gpsLocationService;

	@Override
	public void onCreate()
	{
		super.onCreate();
		
		gpsLocationService=new GPSLocationService(tag);
	}

	@Override
	public IBinder onBind(Intent arg0)
	{
		return null;
	}

	@SuppressWarnings("deprecation")
	@Override
	public void onStart(Intent intent, int startId)
	{
		doService();
		
		super.onStart(intent, startId);
	}

	protected void doService()
	{
		//       
		new Timer().schedule(new TimerTask()
		{
			
			@Override
			public void run()
			{
				//      GPS        
				List<GPSLocation> gpsLocations=gpsLocationService.findAll();
				boolean flag=gpsLocationService.saveToServer(gpsLocations);
				if(flag)
				{
					//        GPS  
					gpsLocationService.delete(gpsLocations);
				}
			}
		}, 0, Constant.GPS_THREAD_TIME_WAIT);

		
	}

}

시스템 BroadcastReceiver 작성
package com.boonya.wtms.service;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class SystemBroadcastReceiver extends BroadcastReceiver
{

	@Override
	public void onReceive(Context context, Intent intent)
	{
		//   Service
		context.startService(new Intent("com.boonya.wtms.service.System_LocalService"));
		Log.i("device-gps-local-service", "GPS          !");

		//   Service
		context.startService(new Intent("com.boonya.wtms.service.System_RemoteService"));
		Log.i("device-gps-remote-service", "GPS          !");
	}

}

안드로이드 매니페스트에서.xml 등록 Receiver 및 서비스
 <receiver android:name="com.boonya.wtms.service.SystemBroadcastReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </receiver>
        

        <service android:name="com.boonya.wtms.service.SystemRemoteService" >
            <intent-filter>
                <action android:name="com.boonya.wtms.service.System_RemoteService" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </service>
        <service android:name="com.boonya.wtms.service.SystemLocalService" >
            <intent-filter>
                <action android:name="com.boonya.wtms.service.System_LocalService" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </service> 

액세스 설정 권한 가입
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" >
    </uses-permission>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" >
    </uses-permission>
    <uses-permission android:name="android.permission.INTERNET" >
    </uses-permission>
    <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" >
    </uses-permission>
    <!-- <uses-permission android:name="android.permission.WRITE_APN_SETTINGS"></uses-permission> -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" >
    </uses-permission>
    <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
    <uses-permission android:name="android.permission.WAKE_LOCK" >
    </uses-permission>
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_GPS" />

주: 여기 GPS 채집은 위성 포지셔닝(채집 과정에서 위성 탐색이 시간이 많이 걸리고 불확실성이 있어서 몇 분 동안 연결될 수도 있고 30분 동안 심지어 연결이 안 될 수도 있다. 이것은 안드로이드 GPS 모듈의 생산 업체에 달려 있다)이다. 상기 권한이 완전하지 않을 수도 있으니 정정하지 않겠습니다.
성능에 대한 고려
(1) 로컬 스토리지 SQLite의 스토리지 기능:
만약에 어떤 대상이 SQLite에서 1kB를 차지한다고 가정하면 1000개의 대상은 약 1MB이고 SQLite는 작은 데이터 양의 저장에 적합하다. 그러면 1000개, 1500개는 정상적으로 저장할 수 있을까?일반적으로 500개(500KB)를 넘지 않는 것이 좋다. 왜냐하면 이것은 마이크로(MINI) 데이터베이스이기 때문이다.
(2) 원격 서버의 저장 압력을 낮춘다.
SQLite의 저장 능력이 제한되어 있기 때문에 로컬 데이터가 서버에 도착하면 하나의 문제가 된다. 그것이 바로 저장, 밀집 저장(복잡도 O(n))이냐, 산열 저장(복잡도 O(1)이냐이다. 이것이 바로 성능을 고려하는 관건적인 요소이다.여기에 사용된 것은Hash와 같은 진실한 산열 저장소가 아니라 대기열을 사용하는 방식으로 저장 압력을 분산시키는 것이다.

좋은 웹페이지 즐겨찾기