[英]How to receive continuous geofence notifications even when app is killed?
I am using the latest geofence api in my app and followed Google's sample code to build the app. 我在我的应用程序中使用了最新的geofence api,并按照Google的示例代码来构建该应用程序。 But it does not work when the app is killed.I have to click the Add Geofence button again to trigger the geofence.I want the geofences to be triggered at all times. 但是当应用程序被杀死时它不起作用。我必须再次单击添加地理围栏按钮以触发地理围栏。我希望可以始终触发地理围栏。 What should i do? 我该怎么办? Here is my code: 这是我的代码:
Main Activity 主要活动
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks
, GoogleApiClient.OnConnectionFailedListener,ResultCallback<Status> {
protected GoogleApiClient googleApiClient;
protected ArrayList<Geofence> geofenceArrayList;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button= (Button) findViewById(R.id.button);
geofenceArrayList = new ArrayList<>();
populateGeofenceList();
buildGoogleApiClient();
}
protected synchronized void buildGoogleApiClient() {
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
@Override
protected void onStart() {
super.onStart();
if (!googleApiClient.isConnected() || !googleApiClient.isConnecting()) {
googleApiClient.connect();
}
}
@Override
protected void onStop() {
super.onStop();
if (googleApiClient.isConnected() || googleApiClient.isConnecting()) {
googleApiClient.disconnect();
}
}
public void populateGeofenceList() {
for (Map.Entry<String, LatLng> entry : Constants.MY_LANDMARKS.entrySet()) {
geofenceArrayList.add(new Geofence.Builder()
.setRequestId(entry.getKey())
.setCircularRegion(entry.getValue().latitude, entry.getValue().longitude, 100)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_DWELL | Geofence.GEOFENCE_TRANSITION_EXIT)
.setLoiteringDelay(300000)
.build());
}
}
private GeofencingRequest getGeofencingRequest(){
GeofencingRequest.Builder builder=new GeofencingRequest.Builder();
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
.addGeofences(geofenceArrayList);
return builder.build();
}
private PendingIntent getGeofencePendingIntent(){
Intent intent=new Intent(this,GeofenceTransitionService.class);
return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
public void addGeofencesButtonHandler(View view){
if(!googleApiClient.isConnected()){
Toast.makeText(this,"Client not connected",Toast.LENGTH_SHORT).show();
return;
}
try {
LocationServices.GeofencingApi.addGeofences(googleApiClient,getGeofencingRequest(),getGeofencePendingIntent()).setResultCallback(this);
}catch (SecurityException securityException){
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onConnected(Bundle bundle) {
}
@Override
public void onConnectionSuspended(int i) {
googleApiClient.connect();
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
@Override
public void onResult(Status status) {
if(status.isSuccess()){
Toast.makeText(this,"Geofence added",Toast.LENGTH_SHORT).show();
}
else {
String errorMessage=GeofenceErrorMessages.getErrorString(this,status.getStatusCode());
Log.e("MainActivity",errorMessage);
}
}
} }
Intent Service 意向服务
public class GeofenceTransitionService extends IntentService {
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public static final String TAG="GeofenceService";
@Override
public void onCreate() {
super.onCreate();
}
public GeofenceTransitionService() {
super(TAG);
}
@Override
protected void onHandleIntent(Intent intent) {
GeofencingEvent geofencingEvent=GeofencingEvent.fromIntent(intent);
if(geofencingEvent.hasError()){
String errorMsg=GeofenceErrorMessages.getErrorString(this,geofencingEvent.getErrorCode());
Log.e(TAG,errorMsg);
return;
}
int geofenceTransition=geofencingEvent.getGeofenceTransition();
if(geofenceTransition== Geofence.GEOFENCE_TRANSITION_ENTER||geofenceTransition==Geofence.GEOFENCE_TRANSITION_DWELL
||geofenceTransition==Geofence.GEOFENCE_TRANSITION_EXIT){
List<Geofence> triggeringGeofences=geofencingEvent.getTriggeringGeofences();
String geofenceTransitionDetails=getGeofenceTransiionDetails(this,geofenceTransition,triggeringGeofences);
sendNotification(geofenceTransitionDetails);
Log.i(TAG,geofenceTransitionDetails);
}
else {
Log.e(TAG,"Invalid Transition : "+geofenceTransition);
}
}
private String getGeofenceTransiionDetails(Context context,int transition,List<Geofence> triggeringGeofences){
String geofenceTransitionString=getTransitionString(transition);
ArrayList GeofenceIdsList=new ArrayList();
for(Geofence geofence:triggeringGeofences){
GeofenceIdsList.add(geofence.getRequestId());
}
String geofencesIdsString= TextUtils.join(", ", GeofenceIdsList);
return geofenceTransitionString+": "+geofencesIdsString;
}
private String getTransitionString(int transitionType){
switch (transitionType){
case Geofence.GEOFENCE_TRANSITION_ENTER:
return "Entered the geofence";
case Geofence.GEOFENCE_TRANSITION_DWELL:
return "Dwelling in the geofence";
case Geofence.GEOFENCE_TRANSITION_EXIT:
return "Exited the geofence";
default:return "Unknown Transition";
}
}
private void sendNotification(String notificationDetails){
Intent notificationIntent=new Intent(getApplicationContext(),MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(notificationIntent);
PendingIntent notificationPendingIntent=stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder=new NotificationCompat.Builder(this);
builder.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(notificationDetails)
.setContentText("Click to return to app")
.setContentIntent(notificationPendingIntent);
builder.setAutoCancel(true);
NotificationManager manager= (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(0,builder.build());
}
} }
django, your question is already answered here. django,您的问题已经在这里得到解答。
https://stackoverflow.com/a/19521823/5320593 https://stackoverflow.com/a/19521823/5320593
You should use BroadcastReceiver instead of IntentService or use them consequentially to avoid ANRs. 您应该使用BroadcastReceiver而不是IntentService或相应地使用它们以避免ANR。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.