2016-12-23 7 views
1

지오 펜싱 앱을 만들려고 시도 중이지만 기본 활동이 시작될 때 지오 펜스를 등록하는 것처럼 보입니다. 앱이 닫힐 때 인 텐트 서비스가 수신을 중지합니다. 그래서, 지오 펜스 로직을 인 텐트 서비스 (인 텐트 처리 코드와 함께)로 옮기고 서비스가 시작되었는지 확인하지만 이제는 서비스가 어떤 의도를 전혀받지 못한다!Android 앱이 지오 펜스를 추가하고 동일한 서비스에서 인 텐트를 수신합니다.

(구글 API 클라이언트가 내장 연결) 서비스의 모든 등 기본적으로, 나는이 '의도 핸들러와 지오 펜스 등록 물건 onConnected 레지스터 지오 펜스, 모두, onCreate에서 이루어집니다

public class GeofenceTransitionsIntentService extends IntentService implements ConnectionCallbacks, OnConnectionFailedListener, ResultCallback<Status> 

서비스 정의 이러한 의도를 처리하기 위해 의도 된 동일한 서비스에서 심하게 차용 한 지오 펜싱 샘플 코드 (문서)를 구현하려고 시도했습니다.

모든 주요 활동은 서비스를 시작하고 서비스에서 수신 된 지오 펜스 알림과 관련된 것들을 그립니다.

자세한 정보가 필요하면 알려주세요.

편집 우리가 더 많은 정보가 필요 것 같다 있도록

확인 - 서비스의 개요 :

public class GeofenceTransitionsIntentService extends IntentService implements ConnectionCallbacks, OnConnectionFailedListener, ResultCallback<Status> { 

    protected static final String TAG = "GeofenceTransitionsIS"; 

    protected GoogleApiClient mGoogleApiClient; 
    protected ArrayList<Geofence> mGeofenceList; 
    private boolean mGeofencesAdded; 
    private PendingIntent mGeofencePendingIntent; 
    private SharedPreferences mSharedPreferences; 

    public GeofenceTransitionsIntentService() { 
     super(TAG); 
    } 

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

     buildGoogleApiClient(); 
     populateGeofenceList(); 
     mGoogleApiClient.connect(); 

    } 

    ... 

    @Override 
    protected void onHandleIntent(Intent intent) { 
     GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent); 
     // handle the intent, send a notification 
    } 


    private void sendNotification(String notificationDetails) { 
     // sends a notification 
    } 

    @Override 
    public void onConnected(Bundle connectionHint) 
    { 
     LocationServices.GeofencingApi.addGeofences(
       mGoogleApiClient, 
       getGeofencingRequest(), 
       getGeofencePendingIntent() 
     ).setResultCallback(this); 
    } 

    // straight out of the example 
    private GeofencingRequest getGeofencingRequest() 
    { 
     ... 
    } 


    // from a branch of the example that reuses the pending intent 
    private PendingIntent getGeofencePendingIntent() 
    { 
     if (mGeofencePendingIntent != null) 
     { 
      return mGeofencePendingIntent; 
     } 

     Intent intent = new Intent(this, GeofenceTransitionsIntentService.class); 
     mGeofencePendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); 
     return mGeofencePendingIntent; 
    } 

    public void populateGeofenceList() { 
     for (thing place : listofplaces) { 
      mGeofenceList.add(...) 
     } 
    } 

    protected synchronized void buildGoogleApiClient() { 
     mGoogleApiClient = new GoogleApiClient.Builder(this) 
       .addConnectionCallbacks(this) 
       .addOnConnectionFailedListener(this) 
       .addApi(LocationServices.API) 
       .build(); 
    } 

    public void onResult(Status status) 
    { 
     // were fences added? usually yes 
    } 
} 

내 연구 실망했다 - 나는 사람들이 할 수있는 주장 참조 브로드 캐스트 리시버 (첫 번째 주석 참조)에서 이런 일을하고 서비스에서는하지 않습니까?

는 내가 통해 일하고 한 모든 버전에서 꽤 난도질 manifest.xml 있습니다

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> 

<application 
    android:allowBackup="true" 
    android:label="@string/app_name" 
    android:theme="@style/AppTheme"> 

    <activity 
     android:name=".MainActivity" 
     android:label="@string/app_name"> 
     <intent-filter> 
      <action android:name="android.intent.action.MAIN"/> 
      <category android:name="android.intent.category.LAUNCHER"/> 
     </intent-filter> 
    </activity> 

    <service android:name=".GeofenceTransitionsIntentService" 
      android:exported="true" 
      android:enabled="true"> 
     <intent-filter > 
      <action android:name="com.aol.android.geofence.ACTION_RECEIVE_GEOFENCE"/> 
     </intent-filter> 
    </service> 

    ... 

</application> 

어느 쪽도 아니 intent-filter도 전혀 도움 서비스 정의에 android:exported="true"를 추가.

+0

난 안드로이드 개발자가 아니야 * – opticaliqlusion

+0

아마도이 질문은 당신을 도울 수 있습니다. http://stackoverflow.com/questions/21090674/android-geofencing-no-coming-intents?rq=1 – TychoTheTaco

+0

@TychoTheTaco는 응답 해 주셔서 감사하지만 효과가있는 것 같지 않습니다 - "내 보낸"추가, 다시 작성 및 다시 시작됨 앱 + 서비스, 아직 아무것도. 디버깅 결과가 더 효과적이지 않을 수도 있습니다. – opticaliqlusion

답변

3

처음으로 인 경우 IntentService을 사용하지 마십시오. 유일한 목적은 단일 의도를 얻고 백그라운드 스레드에서 실행 한 다음 자체를 중지하는 것입니다. 당신이 찾고있는 것은 Service입니다. OS가 리소스가 부족하기 시작할 때까지 잠시 머무를 것입니다.

둘째, 당신이 서비스에 코드를 이동하면, 다음을 수행하십시오

public class GeofenceTransitionsService extends Service implements ConnectionCallbacks, OnConnectionFailedListener, ResultCallback<Status> { 
    //Whatever you need to declare 
    .... 
    GeofencingRequest mRequest; 

    //This is only called once per instance of a Service, so use this to instantiate class variables 
    @Override 
    public void onCreate() { 
     super.onCreate(); 
     buildGoogleApiClient(); 
     mGoogleApiClient.connect(); 
    } 

    //Every time you call context.startService(Intent intent) after the service is created, 
    //this function gets called with the intent you have given it. You can use this to modify or change the geofence api, 
    //passing GeofencingRequests in intents by calling intent.putExtra(...) before sending the intent, and retrieving it here. 
    //I just assume you are passing GeofencingRequest objects, since they are pacelable. 
    @Override 
    public int onStartCommand(Intent intent, int flags, final int startId) { 
     mRequest = intent.getParcelableExtra("request"); //Or whatever the key is for your request. 
     if(mGoogleApiClient.isConnected()){ 
      LocationServices.GeofencingApi.addGeofences(
       mGoogleApiClient, 
       mRequest, 
       getGeofencePendingIntent() 
      ).setResultCallback(this); 
     } 
    } 

    @Override 
    public void onConnected(Bundle connectionHint) 
    { 
     LocationServices.GeofencingApi.addGeofences(
      mGoogleApiClient, 
      mRequest, 
      getGeofencePendingIntent() 
     ).setResultCallback(this); 
    } 

    // from a branch of the example that reuses the pending intent 
    private PendingIntent getGeofencePendingIntent() 
    { 
     if (mGeofencePendingIntent != null) 
     { 
      return mGeofencePendingIntent; 
     } 

     mGeofencePendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(this, GoogleGeofenceReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT); 
     return mGeofencePendingIntent; 
    } 

    //The rest of your code 
    .... 
} 

는 리소스가 부족할 때 경고 경우 많은없이 안드로이드, 서비스를 죽일 수 있음을 유의하십시오. 이 서비스가 더 높은 우선 순위에서 실행되도록하려면 starting in the foreground을 조사 할 것을 강력히 권합니다. 이제 우리는 서비스 설정을 가지고, 당신은 getGeofencePendingIntent() 기능 이제 눈치 챘을 수있는 제 3

BroadcastReceiver 대신가 실행되는 서비스의 사용합니다.

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> 

<application 
    android:allowBackup="true" 
    android:label="@string/app_name" 
    android:theme="@style/AppTheme"> 

    <activity 
     android:name=".MainActivity" 
     android:label="@string/app_name"> 
     <intent-filter> 
      <action android:name="android.intent.action.MAIN"/> 
      <category android:name="android.intent.category.LAUNCHER"/> 
     </intent-filter> 
    </activity> 

    <service android:name=".GeofenceTransitionsService" 
      android:exported="true" 
      android:enabled="true"> 
     <intent-filter > 
      <action android:name="com.aol.android.geofence.ACTION_RECEIVE_GEOFENCE"/> 
     </intent-filter> 
    </service> 
    <receiver android:name=".GoogleGeofenceReceiver"/> 

    ... 

</application> 

아니에요 :

public class GoogleGeofenceReceiver extends BroadcastReceiver { 

    @Override 
    public void onReceive(final Context context, final Intent intent) { 
     GeofencingEvent event = GeofencingEvent.fromIntent(intent); 
     ... 
     //Do whatever you did in your Service handleIntent function here. 
    } 
} 

넷째, 앱이 브로드 캐스트 리시버를 사용하는 것을 알려 매니페스트를 수정해야합니다 : 여기 당신이 것을 설정하는 방법입니다 export 및 enabled 플래그를 사용하는 이유는 분명하지만 enabled는 기본적으로 설정되고 intent-filter가 있으면 exported는 "true"로 기본 설정되어 있기 때문에 선언 할 필요가 없습니다.

이 프로젝트를 통해 많은 이점을 얻었을 것이며, 일반적으로 Android의 고통에 대해 더 잘 이해할 수 있도록 Activity, Service 및 BroadcastReceiver 라이프 사이클을 읽어 보시기 바랍니다.

+0

이것은 완벽합니다. 모든 것을 절대적으로 고치는 비트는 보류중인 의도에 대해 수신기를 사용하는 것입니다. 1) 왜 방송 수신기가되어야합니까? 2) 방송 수신자는 위치가 변경된 후 꽤 오래 걸려 onReceive를 호출 한 것으로 보입니다 - 수신자 (= 지연)와 활동 (= 지연 없음)에 대해 보류중인 의도를 등록하는 것과 근본적인 차이가 있습니까? – opticaliqlusion

+0

한 가지 추가 사항 - 몇 개의 onReceive 후에 브로드 캐스트 리시버가 작동을 멈 춥니 다 (더 이상의 의도는 없습니다). 나는 그것을 조사하고있다. 이 지연 문제의 극단적 인 경우 일 수 있습니다. – opticaliqlusion

+0

1) onHandleIntent 메서드가 백그라운드 스레드에서 실행되는 주 스레드에서 onReceive 메서드가 호출되기 때문에 BroadcastReceiver 일 필요는 없지만 사용하기에 더 적합한 클래스입니다. UI를 조작하려는 경우 매우 중요합니다. 2) 오랜 지연의 이유는 Google 지오 펜스 API가 기기가 지오 펜스에 출입했는지 여부를 확인하기 위해 네트워크 위치를 사용하는 것으로 보이고 네트워크 위치에 대한 부정확성이 높습니다. 마지막으로 테스트 한 시간부터 등록을 위해 지오 펜스를 종료 한 후 추가로 50m가 걸렸습니다. –