AntCopp
AntCopp

Reputation: 163

Geofence Android: PendingIntent doesn't trigger IntentService

I'm trying to develop a Geofence App for Android, that barely have to notify me when enter/exit/dwell in/from/into a Geofence. Despite all questions and answers I red, I'm still not able to figure out my problem.

I think something is wrong with my PendinIntent and/or IntentService. Here what I've done so far.

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();
    }

}

I've omitted some line of code not of interest.

here is my 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());
        }
     }

I've just pasted this IntentService from enter link description here, with few change. Right now, I want to focus on IntentService and its handler: so at the moment I'm not asking for Broadcast Receiver that will be trigged from IntentService after the notification. This is why in my MainActivity there isn't any BroadcastReceiver class declared

My 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>

Few more notes: I really don't know why, but a couple of time the app actually works: my IntentService was fired up from Google Play Service intent and execute a previous version of the code. Weird enough, when I launchede again the same app without any change in the code, IntentService wasn't fired up.

I'm developing with my tablet/smartphone as emulator device: I tried to walk around but no luck at all.

Any help is highly appreciate.

Thanks.

Upvotes: 0

Views: 2832

Answers (1)

AntCopp
AntCopp

Reputation: 163

Following the answer provided by ianhanniballake, I've done more tests with radius that space between 20-30-40 meters, and I found out that all works as intended. As he said, my problems was about the radius settings too small for GPS to recognize its own position.

Sincerely thanks.

Upvotes: 1

Related Questions