2015-01-09 21 views
0

Я пытаюсь разработать приложение Geofence для Android, которое едва нужно уведомить меня при входе/выходе/проживании в/из/в Geofence. Несмотря на все вопросы и ответы, я краснею, я все еще не в состоянии понять свою проблему.Geofence Android: PendingIntent не запускает IntentService

Я думаю, что что-то не так с моим PendinIntent и/или IntentService. Вот что я сделал до сих пор.

MainActivity.java

package it.coppola.geofencedetecttest1; 

import android.app.Dialog; 
import android.app.PendingIntent; 
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.content.IntentFilter; 
import android.location.Location; 
import android.location.LocationManager; 
import android.os.Bundle; 
import android.support.v4.app.DialogFragment; 
import android.support.v4.content.LocalBroadcastManager; 
import android.support.v7.app.ActionBarActivity; 
import android.text.TextUtils; 
import android.util.Log; 
import android.view.View; 
import android.widget.TextView; 

import com.google.android.gms.common.ConnectionResult; 
import com.google.android.gms.common.GooglePlayServicesUtil; 
import com.google.android.gms.common.api.GoogleApiClient; 
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks; 
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener; 
import com.google.android.gms.location.Geofence; 
import com.google.android.gms.location.GeofencingRequest; 
import com.google.android.gms.location.LocationServices; 




public class MainActivity extends ActionBarActivity implements 
ConnectionCallbacks,OnConnectionFailedListener{ 
    private GoogleApiClient mGoogleApiClient; 
    private GeofenceSampleReceiver mGeofenceReceiver; 
    private IntentFilter filter; 
    private Location mCurrentLocation; 
    private PendingIntent mPendingIntent; 





    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     mGoogleApiClient=new GoogleApiClient.Builder(this) 
      .addApi(LocationServices.API) 
      .addConnectionCallbacks(this) 
      .addOnConnectionFailedListener(this) 
      .build(); 
     filter=new IntentFilter(); 
     filter.addAction("it.coppola.geofencedetecttest1.ACTION_GEOFENCES_ERROR"); 
     filter.addAction("it.coppola.geofencedetecttest1.ACTION_GEOFENCES_SUCCESS"); 
     mGeofenceReceiver=new GeofenceSampleReceiver(); 
     LocalBroadcastManager.getInstance(this).registerReceiver(mGeofenceReceiver, filter); 


    } 



    @Override 
    protected void onResume(){ 
     super.onResume(); 
     LocalBroadcastManager.getInstance(this).registerReceiver(mGeofenceReceiver, filter); 

    } 

    @Override 
    protected void onPause(){ 
     super.onPause(); 
     LocalBroadcastManager.getInstance(this).unregisterReceiver(mGeofenceReceiver); 

    } 

    @Override 
    protected void onStop(){ 
     super.onStop(); 

     LocalBroadcastManager.getInstance(this).unregisterReceiver(mGeofenceReceiver); 

    } 

    @Override 
    protected void onDestroy(){ 
     super.onDestroy(); 


    } 

    public void onConnectToLocation(View v){ 
//stuff that happens when i press a button. Here is mGoogleApiClient.connect() 

    } 
    public void onConnected(Bundle connectionHint){ 


     mCurrentLocation= LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); 

     if (mCurrentLocation != null){ 

      TextView lan=(TextView)findViewById(R.id.txtLan); 
      lan.setText(String.valueOf(mCurrentLocation.getLatitude())); 
      TextView lon=(TextView)findViewById(R.id.txtLong); 
      lon.setText(String.valueOf(mCurrentLocation.getLongitude())); 



      Geofence mGeofence1=new Geofence.Builder() 
      .setRequestId("Geofence1") 
      .setCircularRegion(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude(), 5) 
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER|Geofence.GEOFENCE_TRANSITION_EXIT|Geofence.GEOFENCE_TRANSITION_DWELL) 
      .setExpirationDuration(Geofence.NEVER_EXPIRE) 
      .setLoiteringDelay(1000) 
      .build(); 

      mPendingIntent=requestPendingIntent(); 


      GeofencingRequest mGeofenceRequest=new GeofencingRequest.Builder() 
      .addGeofence(mGeofence1) 
      .build(); 


      LocationServices.GeofencingApi.addGeofences(mGoogleApiClient, mGeofenceRequest, mPendingIntent); 
     } 
     else { 

     } 


    } 



    /** 
    * Define a Broadcast receiver that receives updates from connection listeners and 
    * the geofence transition service. 
    */ 



    public class GeofenceSampleReceiver extends BroadcastReceiver { 
     /* 
     * Define the required method for broadcast receivers 
     * This method is invoked when a broadcast Intent triggers the receiver 
     */ 
     @Override 
     public void onReceive(Context context, Intent intent) { 

      // Check the action code and determine what to do 
      String action = intent.getAction(); 
      Log.d("miotag","ho ricevuto questo intent: "+action); 
      if (TextUtils.equals(action, "it.coppola.geofencedetecttest1.ACTION_GEOFENCES_ERROR")){ 
       Log.d("miotag","ho ricevuto un errore dal Location Service"); 
      } 
      else if (TextUtils.equals(action, "it.coppola.geofencedetecttest1.ACTION_GEOFENCES_SUCCESS")){ 
       Log.d("miotag","intent ricevuto: OK"); 
      } 

     } 
    } 

    private PendingIntent requestPendingIntent(){ 

     if (null != mPendingIntent){ 

      return mPendingIntent; 
     } else { 


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

     } 
    } 

    public void stopIt(View v){ 

     LocationServices.GeofencingApi.removeGeofences(mGoogleApiClient, mPendingIntent); 
     Log.d("miotag","geofence rimossa"); 
     mGoogleApiClient.disconnect(); 
    } 

} 

я опустил некоторые строки кода не интереса.

вот мой IntentService

package it.coppola.geofencedetecttest1; 

import java.util.List; 

import android.app.IntentService; 
import android.app.Notification; 
import android.app.NotificationManager; 
import android.app.PendingIntent; 
import android.content.Context; 
import android.content.Intent; 
import android.support.v4.app.NotificationCompat; 

import com.google.android.gms.location.Geofence; 
import com.google.android.gms.location.GeofencingEvent; 

public class GeofenceReceiverSample extends IntentService{ 

public GeofenceReceiverSample(){ 
     super("GeofenceReceiverSample"); 
    } 

    @Override 
     protected void onHandleIntent(Intent intent) { 
     GeofencingEvent geoEvent=GeofencingEvent.fromIntent(intent); 
     if (geoEvent.hasError()) { 
       //todo error process 
      } else { 
       int transitionType = geoEvent.getGeofenceTransition(); 
       if (transitionType == Geofence.GEOFENCE_TRANSITION_ENTER || 
         transitionType == Geofence.GEOFENCE_TRANSITION_EXIT) { 
        List<Geofence> triggerList = geoEvent.getTriggeringGeofences(); 

        for (Geofence geofence : triggerList) { 
         generateNotification(geofence.getRequestId(), "address you defined"); 
        } 
       } 
      } 
     } 

     private void generateNotification(String locationId, String address) { 
      long when = System.currentTimeMillis(); 
      Intent notifyIntent = new Intent(this, MainActivity.class); 
      notifyIntent.putExtra("id", locationId); 
      notifyIntent.putExtra("address", address); 
      notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 

      PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT); 

      NotificationCompat.Builder builder = 
        new NotificationCompat.Builder(this) 
          .setSmallIcon(R.drawable.ic_launcher) 
          .setContentTitle(locationId) 
          .setContentText(address) 
          .setContentIntent(pendingIntent) 
          .setAutoCancel(true) 
          .setDefaults(Notification.DEFAULT_SOUND) 
          .setWhen(when); 

      NotificationManager notificationManager = 
        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 
      notificationManager.notify((int) when, builder.build()); 
     } 
    } 

Я только что вставил этот IntentService из enter link description here, с небольшим изменением. Прямо сейчас, я хочу сосредоточиться на IntentService и его обработчике: так что в данный момент я не прошу о широковещательном приемнике, который будет отправлен из IntentService после уведомления. Вот почему в моем MainActivity нет никакого BroadcastReceiver класс, объявленный

Мой AndroidManifest

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="it.coppola.geofencedetecttest1" 
    android:versionCode="1" 
    android:versionName="1.0" > 

    <uses-sdk 
     android:minSdkVersion="11" 
     android:targetSdkVersion="21" /> 
    <uses-permission android:name="android.permission.INTERNET"/> 
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 
    <!-- 
    <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" /> 
    --> 
    <application 
     android:allowBackup="true" 
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" 
     android:theme="@style/AppTheme" > 
     <activity 
      android:name="it.coppola.geofencedetecttest1.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=".GeofenceReceiverSample" 
     android:exported="false">  
    </service> 

     <receiver android:name="it.coppola.geofencedetecttest1.GeofenceSampleReceiver" 
     android:exported="false"> 
     <intent-filter > 
      <action android:name="it.coppola.geofencedetecttest1.ACTION_RECEIVE_GEOFENCE"/> 
     </intent-filter> 
    </receiver> 


     <meta-data 
      android:name="com.google.android.gms.version" 
      android:value="@integer/google_play_services_version" /> 

    </application> 

</manifest> 

Немного больше нот: Я действительно не знаю, почему, но пару раз приложение на самом деле работает: мой IntentService был уволен из намерения Службы Google Play и выполнил предыдущую версию кода. Как ни странно, когда я снова запустил одно и то же приложение без каких-либо изменений в коде, IntentService не был запущен.

Я развиваю свой планшет/смартфон в качестве эмулятора: я пытался ходить, но мне не повезло.

Любая помощь очень ценится.

Спасибо.

+0

Является ли 'mCurrentLocation'' null'? Похоже, что некоторые протоколирования будут полезны при отладке любых проблем. – ianhanniballake

+0

Нет, он возвращается по назначению. Я использую его для отображения на экране фактической широты и долготы, которые затем передаются как аргумент для Geofence. Я пропустил код, потому что я, хотя это не было важно. Какая информация вам нужна? Извините, я новичок, но я выложу все, что вы просите – AntCopp

+0

5m - очень маленький радиус (большинство GPS-приемников рассчитаны на точность 8-15 м) - вы пробовали использовать больший радиус? – ianhanniballake

ответ

1

После ответа, предоставленного ianhanniballake, я провел больше испытаний с радиусом в 20-30-40 метров, и я узнал, что все работает по назначению. По его словам, мои проблемы состояли в том, что настройки радиуса слишком малы, чтобы GPS распознавала свое собственное положение.

С уважением.

+0

Можете ли вы взглянуть на этот [вопрос] (http://stackoverflow.com/questions/32937515/geofence-not-triggering), пожалуйста? –