Я работаю над простой геозоной, чтобы отображать уведомление, когда пользователь входит или выходит из области.Я выполнил несколько уроков, и код работает без ошибок.Однако, когда я запускаю приложение и покидаю или вхожу в область, ни одно из уведомлений не срабатывает, и я не могу понять, почему.Я предоставил разрешение и могу также подтвердить, что геозоны добавляются без ошибок (Запустите приложение с отладчиком и добавьте геозону, перейдите в отладчик и просмотрите геозону, добавляемую в список)
Когда я запускаю приложениеничего не отображается при входе или выходе из области.Может кто-нибудь увидеть, пропустил ли я что-то или сделал что-то не так?
Любая помощь или руководство было бы здорово, спасибо
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";
}
}