简体   繁体   English

应用在Android Oreo上被杀死时的地理围栏

[英]Geofence when app is killed on Android Oreo

I'm creating a location based app which gets the current location of the user every 'x' minutes in the background, for that I'm planning to use PeriodicWorkRequest using WorkManager API. 我正在创建一个基于位置的应用程序,该应用程序在后台每隔“ x”分钟获取用户的当前位置,为此我计划使用WorkManager API使用PeriodicWorkRequest。

  1. But the thing is the minimum time for repeat interval is 15 minutes, so I thought I could use this Codelab (which uses Broadcast receiver in the pending intent) to get user's location updates, Which of the methods should I be using? 但是事情是重复间隔的最短时间是15分钟,所以我认为我可以使用此Codelab (它在未决的意图中使用Broadcast接收器)来获取用户的位置更新,我应该使用哪种方法?

  2. I'm planning to get Latitude and longitude coordinates from an API and create a Geofence with that latitude and longitude using Periodic Work Request Every 15 minutes in the Background, But the thing is I have Android Oreo and my Geofence does not seem to be triggered or I do not get any notification when my App is killed, I only get when app is in background or in the foreground even after I'm using Broadcast receiver for the pending intent in creating Geofence. 我打算从API获取纬度和经度坐标,并在后台每隔15分钟使用“定期工作请求”使用该纬度和经度创建一个Geofence,但问题是我安装了Android Oreo,而我的Geofence似乎没有被触发或我的应用程序被杀死时,我没有收到任何通知,仅当应用程序在后台或在前台使用时,我才会收到通知,即使我正在使用广播接收器来等待创建Geofence的意图。

  3. Also my periodic work does not seem to run as expected, because I Have put a test notification in the work and it gets executed only when I open the app for the first time and does not work after 15 minutes as it is expected to work, My Main Goal is to Create a periodic work request which runs every 15 minutes in the background, downloads location data from API and creates a geofence with that location, but since my work manager and geofence is not working properly I'm not able to achieve desired results. 另外,我的定期工作似乎没有按预期的方式运行,因为我已经在工作中放置了测试通知,并且只有当我第一次打开该应用程序时该通知才会执行,并且预期会在15分钟后无法正常工作,我的主要目标是创建一个定期工作请求,该请求每隔15分钟在后台运行一次,从API下载位置数据并使用该位置创建地理围栏,但是由于我的工作经理和地理围栏无法正常工作,因此我无法实现预期的结果。 Any help would be appreciated. 任何帮助,将不胜感激。 Here is the Code I'm using. 这是我正在使用的代码。

MainActivity: 主要活动:

package com.example.rohit.geofencefundo;

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {
    private static final int LOC_PERM_REQ_CODE = 1;
    //meters
    private static final int GEOFENCE_RADIUS = 150;
    //in milli seconds
    private static final int GEOFENCE_EXPIRATION = 600000;
    LocationManager locationManager;
    android.location.LocationListener locationListener;
    LatLng userLocation;
    Data data;
    private GoogleMap mMap;
    private GeofencingClient geofencingClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);






       /* geofencingClient = LocationServices.getGeofencingClient(this);
        showCurrentLocationOnMap();*/


        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.g_map);
        mapFragment.getMapAsync(this);

        geofencingClient = LocationServices.getGeofencingClient(this);

        //addresses = geocoder.getFromLocation(lat, lng, 1);
        data = new Data.Builder()
                .putString(BackgroundWork.EXTRA_TITLE, "Message from Activity!")
                .putString(BackgroundWork.EXTRA_TEXT, "Hi! I have come from activity.")
                .build();


    }


    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

        mMap.getUiSettings().setZoomControlsEnabled(true);
        mMap.setMinZoomPreference(15);

        showCurrentLocationOnMap();
        //locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        PeriodicWorkRequest.Builder photoCheckBuilder =
                new PeriodicWorkRequest.Builder(BackgroundWork.class, 15,
                        TimeUnit.MINUTES)
                        .addTag("notifWorker");
// ...if you want, you can apply constraints to the builder here...

// Create the actual work object:
        PeriodicWorkRequest photoCheckWork = photoCheckBuilder.setInputData(data).build();
// Then enqueue the recurring task:
        WorkManager.getInstance().enqueue(photoCheckWork);

        mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
            @Override
            public void onMapClick(LatLng latLng) {
                addLocationAlert(latLng.latitude, latLng.longitude);
            }
        });
    }

    @SuppressLint("MissingPermission")
    private void showCurrentLocationOnMap() {
        if (isLocationAccessPermitted()) {
            requestLocationAccessPermission();
        } else if (mMap != null) {
            mMap.setMyLocationEnabled(true);
        }
    }
    /*public void addFence(View view){

        addLocationAlert(28.360596,75.5863917); //28.360596 75.5863917  budh bhavan
        addLocationAlert( 28.3603219,75.5868534); //ram marg

    }*/






    /*@SuppressLint("MissingPermission")
    private void showCurrentLocationOnMap() {
        if (isLocationAccessPermitted()) {
            requestLocationAccessPermission();
        }
    }*/

    private boolean isLocationAccessPermitted() {
        if (ContextCompat.checkSelfPermission(this,
                android.Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            return true;
        } else {
            return false;
        }
    }

    private void requestLocationAccessPermission() {
        ActivityCompat.requestPermissions(this,
                new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
                LOC_PERM_REQ_CODE);
    }

    @SuppressLint("MissingPermission")
    private void addLocationAlert(double lat, double lng) {
        if (isLocationAccessPermitted()) {
            requestLocationAccessPermission();
        } else {
            String key = "" + lat + "-" + lng;
            Geofence geofence = getGeofence(lat, lng, key);
           /* geofencingClient.addGeofences(getGeofencingRequest(geofence),
                    getGeofencePendingIntent())
                    .addOnCompleteListener(new OnCompleteListener<Void>() {
                        @Override
                        public void onComplete(@NonNull Task<Void> task) {
                            if (task.isSuccessful()) {
                                Toast.makeText(MainActivity.this,
                                        "Location alter has been added",
                                        Toast.LENGTH_SHORT).show();
                            } else {
                                Toast.makeText(MainActivity.this,
                                        "Location alter could not be added",
                                        Toast.LENGTH_SHORT).show();
                            }
                        }
                    });*/


            geofencingClient.addGeofences(getGeofencingRequest(geofence),
                    getGeofencePendingIntent())
                    .addOnSuccessListener(this, new OnSuccessListener<Void>() {
                        @Override
                        public void onSuccess(Void aVoid) {
                            Toast.makeText(MainActivity.this, "added", Toast.LENGTH_SHORT).show();

                        }
                    })
                    .addOnFailureListener(this, new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {

                            Toast.makeText(MainActivity.this, e.toString(), Toast.LENGTH_SHORT).show();
                            e.printStackTrace();

                        }
                    });


        }
    }

    private void removeLocationAlert() {
        if (isLocationAccessPermitted()) {
            requestLocationAccessPermission();
        } else {

            geofencingClient.removeGeofences(getGeofencePendingIntent())
                    .addOnCompleteListener(new OnCompleteListener<Void>() {
                        @Override
                        public void onComplete(@NonNull Task<Void> task) {
                            if (task.isSuccessful()) {
                                Toast.makeText(MainActivity.this,
                                        "Location alters have been removed",
                                        Toast.LENGTH_SHORT).show();

                            } else {
                                Toast.makeText(MainActivity.this,
                                        "Location alters could not be removed",
                                        Toast.LENGTH_SHORT).show();
                            }
                        }
                    });
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        switch (requestCode) {
            case LOC_PERM_REQ_CODE: {
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    showCurrentLocationOnMap();
                    Toast.makeText(MainActivity.this,
                            "Location access permission granted, you try " +
                                    "add or remove location allerts",
                            Toast.LENGTH_SHORT).show();

                }
                return;
            }

        }
    }


    private PendingIntent getGeofencePendingIntent() {


        Intent intent = new Intent(this, LocationAlertBroadcastReceiver.class);
        return PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

    }

    private GeofencingRequest getGeofencingRequest(Geofence geofence) {
        GeofencingRequest.Builder builder = new GeofencingRequest.Builder();

        builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_DWELL);
        builder.addGeofence(geofence);
        return builder.build();
    }

    private Geofence getGeofence(double lat, double lang, String key) {
        return new Geofence.Builder()
                .setRequestId(key)
                .setCircularRegion(lat, lang, GEOFENCE_RADIUS)
                .setExpirationDuration(Geofence.NEVER_EXPIRE)
                .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |
                        Geofence.GEOFENCE_TRANSITION_DWELL)
                .setLoiteringDelay(10000)
                .build();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.remove_loc_alert:
                removeLocationAlert();
                return true;
            default:
                return super.onOptionsItemSelected(item);

        }
    }


}

GeofenceTransitionsJobIntentService: GeofenceTransitionsJobIntentService:

package com.example.rohit.geofencefundo;

import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.location.Address;
import android.location.Geocoder;
import android.os.Build;
import android.support.v4.app.JobIntentService;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.text.TextUtils;
import android.util.Log;

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

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Random;

public class GeofenceTransitionsJobIntentService extends JobIntentService {

    private static final int JOB_ID = 573;

    private static final String TAG = "GeofenceTransitionsIS";

    private static final String CHANNEL_ID = "channel_01";

    /**
     * Convenience method for enqueuing work in to this service.
     */
    public static void enqueueWork(Context context, Intent intent) {
        enqueueWork(context, GeofenceTransitionsJobIntentService.class, JOB_ID, intent);
    }

    /**
     * Handles incoming intents.
     * @param intent sent by Location Services. This Intent is provided to Location
     *               Services (inside a PendingIntent) when addGeofences() is called.
     */
    @Override
    protected void onHandleWork(Intent intent) {
        GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
        if (geofencingEvent.hasError()) {
            String errorMessage = GeofenceErrorMessages.getErrorString(this,
                    geofencingEvent.getErrorCode());
            Log.e(TAG, errorMessage);
            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_DWELL) {

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

            // Get the transition details as a String.
            String geofenceTransitionDetails = getGeofenceTransitionInfo(
                    triggeringGeofences);
            String transitionType = getTransitionString(geofenceTransition);


            sendNotification(transitionType, geofenceTransitionDetails);
            sendNotification2(geofenceTransitionDetails);
            Log.i(TAG, geofenceTransitionDetails);
        } else {
            // Log the error.
            Log.e(TAG, getString(R.string.geofence_transition_invalid_type, geofenceTransition));
        }
    }
    private String getGeofenceTransitionInfo(List<Geofence> triggeringGeofences) {
        ArrayList<String> locationNames = new ArrayList<>();
        for (Geofence geofence : triggeringGeofences) {
            locationNames.add(getLocationName(geofence.getRequestId()));
        }
        String triggeringLocationsString = TextUtils.join(", ", locationNames);

        return triggeringLocationsString;
    }
    private String getLocationNameGeocoder(double lat, double lng) {
        Geocoder geocoder = new Geocoder(this, Locale.getDefault());
        List<Address> addresses = null;

        try {
            addresses = geocoder.getFromLocation(lat,lng, 1);
        } catch (Exception ioException) {
            Log.e("", "Error in getting location name for the location");
        }

        if (addresses == null || addresses.size() == 0) {
            Log.d("", "no location name");
            return null;
        } else {
            Address address = addresses.get(0);
            ArrayList<String> addressInfo = new ArrayList<>();
            for (int i = 0; i <= address.getMaxAddressLineIndex(); i++) {
                addressInfo.add(address.getAddressLine(i));
            }

            return TextUtils.join(System.getProperty("line.separator"), addressInfo);
        }
    }
    private String getLocationName(String key) {
        String[] strs = key.split("-");

        String locationName = null;
        if (strs != null && strs.length == 2) {
            double lat = Double.parseDouble(strs[0]);
            double lng = Double.parseDouble(strs[1]);

            locationName = getLocationNameGeocoder(lat, lng);
        }
        if (locationName != null) {
            return locationName;
        } else {
            return key;
        }
    }


    private String getGeofenceTransitionDetails(
            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 locTransitionType, String locationDetails) {



        NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
        String NOTIFICATION_CHANNEL_ID = "rohit901";

        if(Build.VERSION.SDK_INT >=Build.VERSION_CODES.O){
            @SuppressLint("WrongConstant") NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,"My Notification",NotificationManager.IMPORTANCE_MAX);

            notificationChannel.setDescription("rohit901 channel for app test FCM");
            notificationChannel.enableLights(true);
            notificationChannel.setLightColor(Color.RED);
            notificationChannel.setVibrationPattern(new long[]{0,1000,500,1000});
            notificationChannel.enableVibration(true);

            notificationManager.createNotificationChannel(notificationChannel);

        }

        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this,NOTIFICATION_CHANNEL_ID);
        notificationBuilder.setAutoCancel(true)
                .setDefaults(Notification.DEFAULT_ALL)
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(android.support.compat.R.drawable.notification_icon_background)
                .setTicker("Hearty365")
                .setContentTitle(locTransitionType)
                .setContentText(locationDetails)
                .setContentInfo("info");

        Random random = new Random();
        int m = (int) ((new Date().getTime() / 1000L) % Integer.MAX_VALUE);
        m += random.nextInt(100) + 1;

        notificationManager.notify(m,notificationBuilder.build());



    }




    private String getTransitionString(int transitionType) {
        switch (transitionType) {
            case Geofence.GEOFENCE_TRANSITION_ENTER:
                return getString(R.string.geofence_transition_entered);
            case Geofence.GEOFENCE_TRANSITION_DWELL:
                return "dwell at location";
            case Geofence.GEOFENCE_TRANSITION_EXIT:
                return getString(R.string.geofence_transition_exited);
            default:
                return getString(R.string.unknown_geofence_transition);
        }
    }
}

Background Work (Worker Class): 后台工作(工人班):

package com.example.rohit.geofencefundo;

import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.Toast;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;
import java.util.Random;

import androidx.work.Data;
import androidx.work.Worker;
import androidx.work.WorkerParameters;

public class BackgroundWork extends Worker {
    public static final String EXTRA_TITLE = "title";
    public static final String EXTRA_TEXT = "text";
    public static final String EXTRA_OUTPUT_MESSAGE = "output_message";
    JSONObject jsonPart;
    String result;
    private Context mContext;
    public BackgroundWork(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
        mContext = context;
    }

    @NonNull
    @Override
    public Worker.Result doWork() {
        //do work and shit
        Log.d("work901","work and shit");
        String title = getInputData().getString(EXTRA_TITLE);
        String text = getInputData().getString(EXTRA_TEXT);
        Log.d("work901tit","title from main is "+title);
        Data output = new Data.Builder()
                .putString(EXTRA_OUTPUT_MESSAGE, "I have come from MyWorker!")
                .build();



        sendNotification(title,text);
        new JsonTask().execute("https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=2018-10-20&endtime=2018-10-21&latitude=33.9370804&longitude=135.8284085&maxradiuskm=5000");





        setOutputData(output);
        return Result.SUCCESS;

    }

    private void sendNotification(String title, String text) {



        NotificationManager notificationManager = (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
        String NOTIFICATION_CHANNEL_ID = "rohit901";

        if(Build.VERSION.SDK_INT >=Build.VERSION_CODES.O){
            @SuppressLint("WrongConstant") NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,"My Notification",NotificationManager.IMPORTANCE_MAX);

            notificationChannel.setDescription("rohit901 channel for app test FCM");
            notificationChannel.enableLights(true);
            notificationChannel.setLightColor(Color.RED);
            notificationChannel.setVibrationPattern(new long[]{0,1000,500,1000});
            notificationChannel.enableVibration(true);

            notificationManager.createNotificationChannel(notificationChannel);

        }

        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(mContext,NOTIFICATION_CHANNEL_ID);
        notificationBuilder.setAutoCancel(true)
                .setDefaults(Notification.DEFAULT_ALL)
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(android.support.compat.R.drawable.notification_icon_background)
                .setTicker("Hearty365")
                .setContentTitle(title)
                .setContentText(text)
                .setContentInfo("info");

        Random random = new Random();
        int m = (int) ((new Date().getTime() / 1000L) % Integer.MAX_VALUE);
        m += random.nextInt(100) + 1;

        notificationManager.notify(m,notificationBuilder.build());



    }
    public class JsonTask extends AsyncTask<String,Void,String> {







        @Override
        protected void onPreExecute() {
            // SHOW THE SPINNER WHILE LOADING FEEDS

            //pd.show();


        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);


            //Toast.makeText(FeedBackActivity.this, "DOne", Toast.LENGTH_SHORT).show();
            Log.d("rohit901",s);
            result = s;
            try {
                JSONObject jsonObject = new JSONObject(result);
                String features = jsonObject.getString("features"); //array of features
                //JSONObject jsonObject2 = new JSONObject(features);
                //String geometry = jsonObject2.getString("geometry"); //array of geometry
                //JSONObject jsonObject3 = new JSONObject(geometry);
                //String coordinates = jsonObject3.getString("coordinates");
                JSONArray arr = new JSONArray(features);
                JSONArray locArr;

                Log.d("work901Array",arr.toString());


                for(int i =0;i<arr.length();i++) {





                    jsonPart = arr.getJSONObject(i);
                    //jsonPart2 =
                    locArr = new JSONArray(jsonPart.getJSONObject("geometry").getString("coordinates"));
                    Log.d("geo901","Longitude: "+locArr.getString(0)+", Latitude: "+locArr.getString(1));

                }





            } catch (JSONException e) {
                e.printStackTrace();
            }



        }

        @Override
        protected String doInBackground(String... urls) {



            HttpURLConnection connection = null;
            BufferedReader reader = null;

            try {
                URL url = new URL(urls[0]);
                connection = (HttpURLConnection) url.openConnection();
                connection.connect();


                InputStream stream = connection.getInputStream();

                reader = new BufferedReader(new InputStreamReader(stream));

                StringBuffer buffer = new StringBuffer();
                String line = "";

                while ((line = reader.readLine()) != null) {
                    buffer.append(line+"\n");
                    Log.d("Response: ", "> " + line);   //here u ll get whole response...... :-)

                }

                return buffer.toString();


            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (connection != null) {
                    connection.disconnect();
                }
                try {
                    if (reader != null) {
                        reader.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return null;


        }
    }
}

Rest of my code is here: GitHub 我其余的代码在这里: GitHub

  convertView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent=new Intent(context,ActivityExpenseDetails.class);
            intent.putExtra("employee_name",expenseArrayList.get(position).getEmployee_name());
            intent.putExtra("expense_type",expenseArrayList.get(position).getExpense_type());
            intent.putExtra("amount",expenseArrayList.get(position).getAmount());
            intent.putExtra("description",expenseArrayList.get(position).getDescription());
            context.startActivity(intent);
        }
    });

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Android - 当应用程序被杀时Geofence消失 - Android - Geofence disappearing when app is killed 应用程序被杀死时Firebase不会收到消息-Android Oreo - Firebase don't receive message when app is killed - Android Oreo 当应用程序被杀死时 FCM onMessageReceived 不会触发 (Android Oreo) - FCM onMessageReceived does not fire when app is killed (Android Oreo) 应用被杀死后,Geofence无法正常工作 - Geofence doesn't work when the app is killed 应用程式被杀死时com.google.android.gcm.GCMBroadcastReceiver在android Oreo中不起作用 - com.google.android.gcm.GCMBroadcastReceiver is not working in android Oreo when app is Killed 当应用程序完全被杀死时,如何在android oreo及更高版本的特定时间获得通知? - how to get notification at specific time in android oreo and above when app is completely killed? 当应用不在前台或被杀死时,如何使地理围栏工作? - how to make geofence work when app is not in foreground or it is killed? 即使应用被杀死,如何继续接收地理围栏通知? - How to receive continuous geofence notifications even when app is killed? 应用程序被杀死后,Android Oreo-前台服务| android显示一个通知 - Android oreo - Foreground service once app is killed | android shows a notification 如果应用程序在 android oreo 及更早版本中被杀死,则显式广播接收器不会启动 - Explicit Broadcast receiver dont launch if app is killed in android oreo and earlier
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM