Уведомления Android Geofence не срабатывают - PullRequest
0 голосов
/ 21 октября 2018

Я работаю над простой геозоной, чтобы отображать уведомление, когда пользователь входит или выходит из области.Я выполнил несколько уроков, и код работает без ошибок.Однако, когда я запускаю приложение и покидаю или вхожу в область, ни одно из уведомлений не срабатывает, и я не могу понять, почему.Я предоставил разрешение и могу также подтвердить, что геозоны добавляются без ошибок (Запустите приложение с отладчиком и добавьте геозону, перейдите в отладчик и просмотрите геозону, добавляемую в список)

Когда я запускаю приложениеничего не отображается при входе или выходе из области.Может кто-нибудь увидеть, пропустил ли я что-то или сделал что-то не так?

Любая помощь или руководство было бы здорово, спасибо

MainActivity

public class MainActivity extends AppCompatActivity implements LocationListener {

PendingIntent mGeofencePendingIntent;

private NotesAdapter mAdapter;
private List<Gate> gateListList = new ArrayList<>();
private CoordinatorLayout coordinatorLayout;
private RecyclerView recyclerView;
private TextView noNotesView;

private DBMain dbMain;

protected ArrayList<Geofence> mGeofenceList;
protected GoogleApiClient mGoogleApiClient;
private Button mAddGeofencesButton;

public static final String TAG = "Activity";
LocationRequest mLocationRequest;

double currentLatitude = 53.258234;
double currentLongitude = -6.14828;

private static final int MY_PERMISSIONS_REQUEST_CALL_PHONE = 101;
private static final int MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 108;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    //setSupportActionBar(toolbar);

    coordinatorLayout = findViewById(R.id.coordinator_layout);
    recyclerView = findViewById(R.id.recycler_view);
    noNotesView = findViewById(R.id.empty_notes_view);


    dbMain = new DBMain(this);

    gateListList.addAll(dbMain.getAllGates());

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            showNoteDialog(false, null, -1);
        }
    });

    mAdapter = new NotesAdapter(this, gateListList);
    RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
    recyclerView.setLayoutManager(mLayoutManager);
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    recyclerView.addItemDecoration(new MyDividerItemDecoration(this, LinearLayoutManager.VERTICAL, 16));
    recyclerView.setAdapter(mAdapter);

    toggleEmptyNotes();

    //checking and grantting permission to locatoin from user
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
        }
        return;
    } else {
        //continue Task
    }

    /**
     * On long press on RecyclerView item, open alert dialog
     * with options to choose
     * Edit and Delete
     * */
    recyclerView.addOnItemTouchListener(new RecyclerTouchListener(this,
            recyclerView, new RecyclerTouchListener.ClickListener() {
        @Override
        public void onClick(View view, final int position) {
        }

        @Override
        public void onLongClick(View view, int position) {
            showActionsDialog(position);
        }
    }));

    if (savedInstanceState == null) {

        mGeofenceList = new ArrayList<Geofence>();

        int resp = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        if (resp == ConnectionResult.SUCCESS) {

            initGoogleAPIClient();
            populateGeofenceList();


        } else {
            Log.e(TAG, "Your Device doesn't support Google Play Services.");
        }

        // Create the LocationRequest object
        mLocationRequest = LocationRequest.create()
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                .setInterval(1 * 1000)        // 10 seconds, in milliseconds
                .setFastestInterval(1 * 1000); // 1 second, in milliseconds

    }
}

public void populateGeofenceList() {
    for (Map.Entry<String, LatLng> entry : Constants.LANDMARKS.entrySet()) {
        mGeofenceList.add(new Geofence.Builder()
                .setRequestId(entry.getKey())
                .setCircularRegion(
                        entry.getValue().latitude,
                        entry.getValue().longitude,
                        Constants.GEOFENCE_RADIUS_IN_METERS
                )
                .setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS)
                .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |
                        Geofence.GEOFENCE_TRANSITION_EXIT)
                .build());
    }
}


/**
 * Opens dialog with Edit - Delete options
 * Edit - 0
 * Delete - 0
 */
private void showActionsDialog(final int position) {
    CharSequence colors[] = new CharSequence[]{"Edit", "Delete"};

    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle("Choose option");
    builder.setItems(colors, new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            if (which == 0) {
                showNoteDialog(true, gateListList.get(position), position);
            } else {
                dbMain.deleteGate(position);
            }
        }
    });
    builder.show();
}

/**
 * Shows alert dialog with EditText options to enter / edit
 * a gate.
 * when shouldUpdate=true, it automatically displays old gate and changes the
 * button text to UPDATE
 */
private void showNoteDialog(final boolean shouldUpdate, final Gate gate, final int position) {
    LayoutInflater layoutInflaterAndroid = LayoutInflater.from(getApplicationContext());
    View view = layoutInflaterAndroid.inflate(R.layout.note_dialog, null);

    AlertDialog.Builder alertDialogBuilderUserInput = new AlertDialog.Builder(MainActivity.this);
    alertDialogBuilderUserInput.setView(view);

    final EditText inputGate = view.findViewById(R.id.gate);
    final EditText inputPhoneNumber = view.findViewById(R.id.number);
    final EditText inputRadius = view.findViewById(R.id.radius);

    TextView dialogTitle = view.findViewById(R.id.dialog_title);
    dialogTitle.setText(!shouldUpdate ? getString(R.string.lbl_new_note_title) : getString(R.string.lbl_edit_note_title));

    if (shouldUpdate && gate != null) {
        inputGate.setText(gate.getGate());
        inputPhoneNumber.setText(gate.getPhonenumber());
    }
    alertDialogBuilderUserInput
            .setCancelable(false)
            .setPositiveButton(shouldUpdate ? "update" : "save", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialogBox, int id) {

                }
            })
            .setNegativeButton("cancel",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialogBox, int id) {
                            dialogBox.cancel();
                        }
                    });

    final AlertDialog alertDialog = alertDialogBuilderUserInput.create();
    alertDialog.show();

    alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // Show toast message when no text is entered
            if (TextUtils.isEmpty(inputGate.getText().toString())) {
                Toast.makeText(MainActivity.this, "Enter gate!", Toast.LENGTH_SHORT).show();
                return;
            } else {
                alertDialog.dismiss();
            }

            // check if user updating gate
            if (shouldUpdate && gate != null) {
                // update gate by it's id
                dbMain.updateGate(inputGate.getText().toString(), gate.getGate());
            } else {
                // create new gate
                String radiusString = inputRadius.getText().toString();
                int radius = Integer.parseInt(radiusString);

                double latitude = 53.258234;
                double longitude = -6.14828;

                //dbMain.insertGate(inputGate.getText().toString(), inputPhoneNumber.getText().toString(), latitude, longitude, radius);

                createGeofences(latitude, longitude, radius);

                refresh();

            }
        }
    });
}

private void refresh()
{
    mAdapter.notifyDataSetChanged();

    toggleEmptyNotes();
}


private void toggleEmptyNotes() {
    // you can check notesList.size() > 0

    if (dbMain.getGatesCount() > 0) {
        noNotesView.setVisibility(View.GONE);
    } else {
        noNotesView.setVisibility(View.VISIBLE);
    }
}

public void initGoogleAPIClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addApi(LocationServices.API)
            .addConnectionCallbacks(connectionAddListener)
            .addOnConnectionFailedListener(connectionFailedListener)
            .build();
    mGoogleApiClient.connect();
}

private GoogleApiClient.ConnectionCallbacks connectionAddListener =
        new GoogleApiClient.ConnectionCallbacks() {
            @Override
            public void onConnected(Bundle bundle) {
                Log.i(TAG, "onConnected");

                Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);


                if (location == null) {
                    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, MainActivity.this);

                } else {
                    //If everything went fine lets get latitude and longitude
                    currentLatitude = location.getLatitude();
                    currentLongitude = location.getLongitude();

                    Log.i(TAG, currentLatitude + " WORKS " + currentLongitude);

                    //createGeofences(currentLatitude, currentLongitude);
                    //registerGeofences(mGeofenceList);
                }

                try{
                    LocationServices.GeofencingApi.addGeofences(
                            mGoogleApiClient,
                            getGeofencingRequest(),
                            getGeofencePendingIntent()
                    ).setResultCallback(new ResultCallback<Status>() {

                        @Override
                        public void onResult(Status status) {
                            if (status.isSuccess()) {
                                Log.i(TAG, "Saving Geofence");

                            } else {
                                Log.e(TAG, "Registering geofence failed: " + status.getStatusMessage() +
                                        " : " + status.getStatusCode());
                            }
                        }
                    });

                } catch (SecurityException securityException) {
                    // Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
                    Log.e(TAG, "Error");
                }
            }

            @Override
            public void onConnectionSuspended(int i) {

                Log.e(TAG, "onConnectionSuspended");

            }
        };

private GoogleApiClient.OnConnectionFailedListener connectionFailedListener =
        new GoogleApiClient.OnConnectionFailedListener() {
            @Override
            public void onConnectionFailed(ConnectionResult connectionResult) {
                Log.e(TAG, "onConnectionFailed");
            }
        };

/**
 * Create a Geofence list
 */
public void createGeofences(double latitude, double longitude, int radius) {
    String id = UUID.randomUUID().toString();
    Geofence fence = new Geofence.Builder()
            .setRequestId(id)
            .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)
            .setCircularRegion(latitude, longitude, radius)
            .setExpirationDuration(Geofence.NEVER_EXPIRE)
            .build();
    mGeofenceList.add(fence);


}

private GeofencingRequest getGeofencingRequest() {
    GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
    builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
    builder.addGeofences(mGeofenceList);
    return builder.build();
}

private PendingIntent getGeofencePendingIntent() {
    // Reuse the PendingIntent if we already have it.
    if (mGeofencePendingIntent != null) {
        return mGeofencePendingIntent;
    }
    Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
    // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when
    // calling addGeofences() and removeGeofences().
    return PendingIntent.getService(this, 0, intent, PendingIntent.
            FLAG_UPDATE_CURRENT);
}

//@Override
public void onLocationChanged(Location location) {
    currentLatitude = location.getLatitude();
    currentLongitude = location.getLongitude();
    Log.i(TAG, "onLocationChanged");
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    switch (requestCode) {
        case 108:
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                //continueYourTask
            }
            break;
        default:
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

GeofenceTransitionsIntentService

public GeofenceTransitionsIntentService(String name) {
    super(name);
}

protected void onHandleIntent(Intent intent) {
    GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
    Toast.makeText(this, "service get start", Toast.LENGTH_LONG).show();

    Log.e("service", "geofencing service started");
    if (geofencingEvent.hasError()) {
        //String errorMessage = GeofenceErrorMessages.getErrorString(this,geofencingEvent.getErrorCode());
        Toast.makeText(this, "Error Oh NO!", Toast.LENGTH_LONG).show();
        return;
    }

    // Get the transition type.
    int geofenceTransition = geofencingEvent.getGeofenceTransition();

    // Test that the reported transition was of interest.
    if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
            geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT || geofenceTransition == Geofence.GEOFENCE_TRANSITION_DWELL) {

        // Get the geofences that were triggered. A single event can trigger
        // multiple geofences.
        List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();

        Toast.makeText(this, "you are inside range", Toast.LENGTH_LONG).show();
        // Get the transition details as a String.
        String geofenceTransitionDetails = getGeofenceTransitionDetails(geofenceTransition, triggeringGeofences);

        // Send notification and log the transition details.
        sendNotification(geofenceTransitionDetails);
        Log.e("geofancing", "you are inside range");

    } else {
        Toast.makeText(this, "Invalid_Transition", Toast.LENGTH_LONG).show();
    }
}

private String getGeofenceTransitionDetails(
        // Context context,
        int geofenceTransition,
        List<Geofence> triggeringGeofences) {

    String geofenceTransitionString = getTransitionString(geofenceTransition);

    // Get the Ids of each geofence that was triggered.
    ArrayList<String> triggeringGeofencesIdsList = new ArrayList<>();
    for (Geofence geofence : triggeringGeofences) {
        triggeringGeofencesIdsList.add(geofence.getRequestId());
    }
    String triggeringGeofencesIdsString = TextUtils.join(", ", triggeringGeofencesIdsList);

    return geofenceTransitionString + ": " + triggeringGeofencesIdsString;
}

private void sendNotification(String notificationDetails) {
    // Create an explicit content Intent that starts MainActivity.
    Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);

    // Get a PendingIntent containing the entire back stack.
    android.app.TaskStackBuilder stackBuilder = android.app.TaskStackBuilder.create(this);
    stackBuilder.addParentStack(MainActivity.class).addNextIntent(notificationIntent);
    PendingIntent notificationPendingIntent =
            stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);

    // Get a notification builder that's compatible with platform versions >= 4
    NotificationCompat.Builder builder = new NotificationCompat.Builder(this);

    // Define the notification settings.
    builder.setColor(Color.RED)
            .setContentTitle(notificationDetails)
            .setContentText("Click notification to return to App")
            .setContentIntent(notificationPendingIntent)
            .setAutoCancel(true);

    // Fire and notify the built Notification.
    NotificationManager notificationManager =
            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(0, builder.build());
}

private String getTransitionString(int transitionType) {
    switch (transitionType) {
        case Geofence.GEOFENCE_TRANSITION_ENTER:
            return "Entered";
        case Geofence.GEOFENCE_TRANSITION_EXIT:
            return "Exited";
        default:
            return "Unknown";

    }
}
...