Android 地理围栏设置/配置是应该从活动类完成,还是可以使用服务类完成?

Android 地理围栏设置/配置是应该从活动类完成,还是可以使用服务类完成?,android,geolocation,android-pendingintent,geofencing,android-geofence,Android,Geolocation,Android Pendingintent,Geofencing,Android Geofence,我浏览了安卓系统的地理围栏文档和网络上的其他几个例子。它们的共同点是,从活动初始化geofence客户端,并在活动本身上添加geofence和分配挂起的意图。在挂起的intent中,它们传递intent服务类或广播接收器类。我的第一个问题 如果我在一个活动中初始化一个类,比如说“GeofenceActivity”,然后我关闭该应用程序(按下后退按钮也会将其从最近使用的应用程序中删除),那么在挂起的Intent中传递的Intent服务或广播接收器类是否仍然能够获得enter and exist的事

我浏览了安卓系统的地理围栏文档和网络上的其他几个例子。它们的共同点是,从活动初始化geofence客户端,并在活动本身上添加geofence和分配挂起的意图。在挂起的intent中,它们传递intent服务类或广播接收器类。我的第一个问题

  • 如果我在一个活动中初始化一个类,比如说“GeofenceActivity”,然后我关闭该应用程序(按下后退按钮也会将其从最近使用的应用程序中删除),那么在挂起的Intent中传递的Intent服务或广播接收器类是否仍然能够获得enter and exist的事件通知

  • 我可以在服务类中初始化该类,并在此类中准备挂起的意图吗

  • 我需要的是,我希望设置的环境是这样一种方式,即使当应用程序不工作时(我所说的应用程序是指UI,服务将运行),我也希望收到有关geofence事件的通知

    Service class:
    package com.services;
    
    
    import android.Manifest;
    import android.app.NotificationManager;
    import android.app.PendingIntent;
    import android.app.TaskStackBuilder;
    import android.content.Context;
    import android.content.Intent;
    import android.content.pm.PackageManager;
    import android.graphics.Color;
    import android.location.Address;
    import android.location.Geocoder;
    import android.location.Location;
    import android.media.MediaPlayer;
    import android.os.CountDownTimer;
    import android.os.Handler;
    import android.os.Looper;
    import android.support.annotation.NonNull;
    import android.support.v4.app.ActivityCompat;
    import android.support.v4.app.JobIntentService;
    import android.support.v4.app.NotificationCompat;
    import android.support.v4.content.LocalBroadcastManager;
    import android.text.TextUtils;
    import android.util.Log;
    import android.widget.Toast;
    
    import com.google.android.gms.location.Geofence;
    import com.google.android.gms.location.GeofenceStatusCodes;
    import com.google.android.gms.location.GeofencingClient;
    import com.google.android.gms.location.GeofencingEvent;
    import com.google.android.gms.location.GeofencingRequest;
    import com.google.android.gms.location.LocationRequest;
    import com.google.android.gms.location.LocationServices;
    import com.google.android.gms.tasks.OnCompleteListener;
    import com.google.android.gms.tasks.Task;
    import receiver.GeofenceBroadcastReceiver;
    
    import java.util.ArrayList;
    import java.util.Calendar;
    import java.util.Date;
    import java.util.List;
    import java.util.Locale;
    
    public class GeofenceTransitionsJobIntentService extends JobIntentService {
    
        static MediaPlayer mp;
    
        private static final String GEO_PENDING_KEY = "MMW-GEOFENCING-KEY";
        private static PendingIntent mGeofencePendingIntent;
        private static LocationRequest mLocationRequest;
        public static GeofencingClient GEOFENCING_CLIENT;
        private static Context geocontext;
        private static CountDownTimer timer;
        private static double latitude, longitude;
        private static float radius;
        private static ArrayList<Geofence> mGeofenceList;
    
        private static final String IDENTIFIER = "LocationAlertIS";
        int geofenceTransition;
        private static final int JOB_ID = 573;
        //private static final String TAG = "GeofenceTransitionsIS";
        private static final String TAG = "Ganesh";
        private static final String CHANNEL_ID = "channel_01";
    
        @Override
        public void onCreate() {
            super.onCreate();
            Log.i(TAG, "onCreate: GEO FENCING STARTED");
            SetTimerStatus(true);
            PrepareGeoClient();
        }
    
        @Override
        public void onDestroy() {
            Log.i(TAG, "onDestroy: GEO FENCING DESTROYED XXXX");
            SetTimerStatus(false);
            super.onDestroy();
        }
    
        public static void enqueueWork(Context context, Intent intent) {
            Toast.makeText(context, "ENQUING FIRST PHASE", Toast.LENGTH_LONG).show();
            enqueueWork(context, GeofenceTransitionsJobIntentService.class, JOB_ID, intent);
        }
    
    
        @Override
        protected void onHandleWork(Intent intent) {
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    try {
                        Toast.makeText(geocontext, "ENQUING FINAL PHASE", Toast.LENGTH_LONG).show();
                    }catch (Exception ex){
    
                    }
                }
            });
    
    
            GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
    
            if (geofencingEvent.hasError()) {
                Log.e(IDENTIFIER, "" + getErrorString(geofencingEvent.getErrorCode()));
                return;
            }
    
            Log.i(IDENTIFIER, geofencingEvent.toString());
    
            geofenceTransition = geofencingEvent.getGeofenceTransition();
    
            if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
                    geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
    
                //logic to process geofence event
            }
        }
    
        private String getGeofenceTransitionInfo(List<Geofence> triggeringGeofences) {
            ArrayList<String> locationNames = new ArrayList<>();
            for (Geofence geofence : triggeringGeofences) {
                locationNames.add(getLocationName(geofence.getRequestId()));
                System.out.println("GET LOACTION NAME");
            }
            String triggeringLocationsString = TextUtils.join(", ", locationNames);
    
            return triggeringLocationsString;
        }
    
        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);
            } else System.out.println("NULLLLLLLLLLLLLLLLL");
            if (locationName != null) {
                return locationName;
            } else {
                return key;
            }
        }
    
        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");
                Toast.makeText(this, "Error in getting location name for the location", Toast.LENGTH_LONG).show();
            }
    
            if (addresses == null || addresses.size() == 0) {
                Log.d("", "no location name");
                Toast.makeText(this, "No Location name", Toast.LENGTH_LONG).show();
    
                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 getErrorString(int errorCode) {
            switch (errorCode) {
                case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE:
                    return "Geofence not available";
                case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES:
                    return "geofence too many_geofences";
                case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS:
                    return "geofence too many pending_intents";
                default:
                    return "geofence error";
            }
        }
    
        private String getTransitionString(int transitionType) {
            switch (transitionType) {
                case Geofence.GEOFENCE_TRANSITION_ENTER:
                    return "location entered";
                case Geofence.GEOFENCE_TRANSITION_EXIT:
                    return "location exited";
                case Geofence.GEOFENCE_TRANSITION_DWELL:
                    return "dwell at location";
                default:
                    return "location transition";
            }
        }
    
        private void notifyLocationAlert(String locTransitionType, String locationDetails) {
    
            // Create an Intent for the activity you want to start
            Intent resultIntent = new Intent(this, SettingTabMainMapActivity.class);
            // Create the TaskStackBuilder and add the intent, which inflates the back stack
            TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
            stackBuilder.addNextIntentWithParentStack(resultIntent);
            // Get the PendingIntent containing the entire back stack
            PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
    
            String CHANNEL_ID = "Zoftino";
            NotificationCompat.Builder builder =
                    new NotificationCompat.Builder(geocontext, CHANNEL_ID)
                            .setSmallIcon(R.drawable.mmw_red_white_60)
                            .setContentTitle(locTransitionType)
                            .setContentText(locationDetails)
                            .setContentIntent(resultPendingIntent)
                            .setPriority(NotificationManager.IMPORTANCE_HIGH);
    
            //Vibration
            builder.setVibrate(new long[]{1000, 1000, 1000, 1000, 1000});
    
            //LED
            builder.setLights(Color.RED, 10000, 10000);
    
    
            builder.setAutoCancel(true);
    
            NotificationManager mNotificationManager =
                    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    
            mNotificationManager.notify(0, builder.build());
        }
    
        private void triggerDetection() {
            Log.d("sender", "Broadcasting message");
            Intent intent = new Intent("trigger-detection");
            // You can also include some extra data.
            intent.putExtra("clear", "This is my message6!");
            LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
        }
    
        private void triggerGeofence(double lat, double longs) {
    
            Patient patient = (Patient) MedWatchApp.getCurrentUser();
    
            if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
    
               //alert geofence exit
            }
    
            else if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER) {
    
            //alert geofence entrance
        }
    
        static void SetTimerStatus(boolean start){
            try{
                if(!start) {
                    timer.cancel();
                    timer = null;
                }
                else{
                    if(timer==null){
                        timer = new CountDownTimer(3600000, 5000) {
                            @Override
                            public void onTick(long l) {
                                if(GEOFENCING_CLIENT == null){
                                    Log.i(TAG, "onTick: GEO CLIENT NULL");
                                }else{
                                    Log.i(TAG, "onTick: OK GEO CLIENT NOT NULL");
                                }
                                if(geocontext == null){
                                    Log.i(TAG, "onTick: CONTEXT NULLLL");
                                }else{
                                    Log.i(TAG, "onTick: CONTEXT FINE");
                                }
                            }
    
                            @Override
                            public void onFinish() {
    
                            }
                        };
                        timer.start();
                    }
                }
            }catch (Exception ex){
    
            }
        }
    
        public static void SetGeofenceClient(GeofencingClient client){
            GEOFENCING_CLIENT = client;
        }
    
        public static void ResetGeofenceClient(){
            GEOFENCING_CLIENT = null;
        }
        public static GeofencingClient GetGeofenceingClient(){
            return GEOFENCING_CLIENT;
    //        return  null;
        }
        public static void SetGeoContext(Context context){
            geocontext = context;
        }
    
        private static void PrepareGeoClient(){
            if(GEOFENCING_CLIENT==null){
                mGeofenceList = new ArrayList<>();
                PrepareAllGeoCoordinate(-33.8502747,151.032907,20);
                PrepareAllGeoCoordinate(-33.8502747,151.029999,20);
                PrepareAllGeoCoordinate(-33.8492767,151.0328641,20);
                PrepareAllGeoCoordinate(-33.8499534,151.0297315,10);
                PrepareAllGeoCoordinate(-33.8500069,151.0297422,10);
                PrepareAllGeoCoordinate(-33.8500247,151.0297529,10);
                GEOFENCING_CLIENT = LocationServices.getGeofencingClient(geocontext);
                //createLocationRequest();
                RemoveGeoLocations();
            }
            AddGeoLocation();
        }
    
        //specifications of real location updates.
        protected static void createLocationRequest() {
            mLocationRequest = LocationRequest.create();
            mLocationRequest.setInterval(2000);
            mLocationRequest.setFastestInterval(2000);
            mLocationRequest.setSmallestDisplacement(10);
            mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        }
    
        protected static void RemoveGeoLocations(){
            GEOFENCING_CLIENT.removeGeofences(getGeofencePendingIntent()).addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    if(task.isSuccessful()){
                        Toast.makeText(geocontext, "REMOVED>>>", Toast.LENGTH_LONG).show();
                    }else{
                        Toast.makeText(geocontext, "FALED REMOVED>>>", Toast.LENGTH_LONG).show();
                    }
    
                }
            });
        }
    
    protected static void AddGeoLocation(){
        if (ActivityCompat.checkSelfPermission(geocontext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        GEOFENCING_CLIENT.addGeofences(getGeofencingRequest(), getGeofencePendingIntent())
                .addOnCompleteListener(new OnCompleteListener<Void>() {
                    @Override
                    public void onComplete(@NonNull Task<Void> task) {
                        if (task.isSuccessful()) {
                            Toast.makeText(geocontext,
                                    "Location alter has been added",
                                    Toast.LENGTH_SHORT).show();
                        } else {
                            Toast.makeText(geocontext,
                                    "Geofence could not be added",
                                    Toast.LENGTH_SHORT).show();
                        }
                    }
                });
    }
    //geofence triggering alert process
    private static PendingIntent getGeofencePendingIntent() {
        // Reuse the PendingIntent if we already have it.
        if (mGeofencePendingIntent != null) {
            return mGeofencePendingIntent;
        }
        Intent intent = new Intent(geocontext, GeofenceBroadcastReceiver.class);
        mGeofencePendingIntent = PendingIntent.getBroadcast(geocontext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        return mGeofencePendingIntent;
    }
    //geofence triggering alert process
    private static GeofencingRequest getGeofencingRequest(Geofence geofence) {
        // The INITIAL_TRIGGER_ENTER flag indicates that geofencing service should trigger a
        // GEOFENCE_TRANSITION_ENTER notification when the geofence is added and if the device
        // is already inside that geofence.
        GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
        // builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
        builder.addGeofence(geofence);
    //        builder.setInitialTrigger(4);
    
    
    
        builder.addGeofences(mGeofenceList);
        return builder.build();
    }
    
    //geofence triggering alert process
    private static GeofencingRequest getGeofencingRequest() {
            GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
            // The INITIAL_TRIGGER_ENTER flag indicates that geofencing service should trigger a
            // GEOFENCE_TRANSITION_ENTER notification when the geofence is added and if the device
            // is already inside that geofence.
    //        builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER |GeofencingRequest.INITIAL_TRIGGER_DWELL);
            builder.addGeofences(mGeofenceList);
            return builder.build();
        }
    public static void SetGeoParams(double lat, double lng, float rad){
            latitude = lat;
            longitude = lng;
            radius = rad;
        }
    
    private static void PrepareAllGeoCoordinate(double lat, double lng, int rad){
        //Create dummy data for testing
                mGeofenceList.add(new Geofence.Builder()
                        .setRequestId(String.format("%f-%f",lat,lng))
                        .setCircularRegion(
                                lat,
                                lng,
                                rad
                        )
                        .setLoiteringDelay(60000)
                        .setExpirationDuration(Geofence.NEVER_EXPIRE)
                        .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |
                                Geofence.GEOFENCE_TRANSITION_EXIT | Geofence.GEOFENCE_TRANSITION_DWELL)
    
                        // Create the geofence.
                        .build());
                //
            }
        }
    
    
        I set the context from MainActivity calling following method in onCreate method:
        void PrepareGeoFence(){
        //        -33.8502747,151.032907
                GeofenceTransitionsJobIntentService.SetGeoContext(this);
                GeofenceTransitionsJobIntentService.SetGeoParams(-33.8502747,
        //                151.029999
                        151.032907,
                        10f);
        this.startService(new Intent(this, GeofenceTransitionsJobIntentService.class));
            }
    
    服务类别:
    包com.services;
    导入android.Manifest;
    导入android.app.NotificationManager;
    导入android.app.pendingent;
    导入android.app.TaskStackBuilder;
    导入android.content.Context;
    导入android.content.Intent;
    导入android.content.pm.PackageManager;
    导入android.graphics.Color;
    导入android.location.Address;
    导入android.location.Geocoder;
    导入android.location.location;
    导入android.media.MediaPlayer;
    导入android.os.CountDownTimer;
    导入android.os.Handler;
    导入android.os.Looper;
    导入android.support.annotation.NonNull;
    导入android.support.v4.app.ActivityCompat;
    导入android.support.v4.app.JobIntentService;
    导入android.support.v4.app.NotificationCompat;
    导入android.support.v4.content.LocalBroadcastManager;
    导入android.text.TextUtils;
    导入android.util.Log;
    导入android.widget.Toast;
    导入com.google.android.gms.location.geofense;
    导入com.google.android.gms.location.GeofenceStatusCodes;
    导入com.google.android.gms.location.GeofencingClient;
    导入com.google.android.gms.location.GeofencingEvent;
    导入com.google.android.gms.location.GeofencingRequest;
    导入com.google.android.gms.location.LocationRequest;
    导入com.google.android.gms.location.LocationServices;
    导入com.google.android.gms.tasks.OnCompleteListener;
    导入com.google.android.gms.tasks.Task;
    导入接收方。导入接收方;
    导入java.util.ArrayList;
    导入java.util.Calendar;
    导入java.util.Date;
    导入java.util.List;
    导入java.util.Locale;
    公共类GeofenceTransitionsJobIntentService扩展了JobIntentService{
    静态媒体播放器mp;
    私有静态最终字符串GEO_PENDING_KEY=“MMW-geovinging-KEY”;
    专用静态悬挂式帐篷管理围栏悬挂式帐篷;
    专用静态位置请求mLocationRequest;
    公共静态土工围栏客户机土工围栏客户机;
    私有静态上下文和地理上下文;
    专用静态倒计时;
    私人静态双纬度、经度;
    私有静态浮动半径;
    私有静态数组列表mGeofenceList;
    私有静态最终字符串标识符=“LocationAlertIS”;
    国际地理过渡;
    私有静态最终整型作业\u ID=573;
    //私有静态最终字符串TAG=“GeoFenceTransitions”;
    私有静态最终字符串TAG=“Ganesh”;
    专用静态最终字符串通道\u ID=“通道\u 01”;
    @凌驾
    public void onCreate(){
    super.onCreate();
    Log.i(标记“onCreate:GEO Fenging Start”);
    SetTimerStatus(真);
    PrepareGeoClient();
    }
    @凌驾
    公共空间{
    日志i(标签“onDestroy:GEO-Ferning被毁XXXX”);
    SetTimerStatus(假);
    super.ondestory();
    }
    公共静态void排队工作(上下文、意图){
    Toast.makeText(上下文,“ENQUING第一阶段”,Toast.LENGTH_LONG.show();
    排队工作(上下文、GeofenceTransitionsJobIntentService.class、作业ID、意图);
    }
    @凌驾
    手工制品上的保护空隙(意图){
    新的处理程序(Looper.getMainLooper()).post(新的Runnable()){
    @凌驾
    公开募捐{
    试一试{
    Toast.makeText(地理上下文,“ENQUING FINAL PHASE”,Toast.LENGTH_LONG.show();
    }捕获(例外情况除外){
    }
    }
    });
    GeofencingEvent GeofencingEvent=GeofencingEvent.fromIntent(intent);
    if(geofencingEvent.hasError()){
    Log.e(标识符“”+getErrorString(geofencingEvent.getErrorCode());
    回来
    }
    Log.i(标识符geofencingEvent.toString());
    geofenceTransition=geofencingEvent.getGeofenceTransition();
    如果(geofenceTransition==Geofence.Geofence\u TRANSITION\u输入||
    geofenceTransition==Geofence.Geofence_TRANSITION_EXIT){
    //处理地理围栏事件的逻辑
    }
    }
    私有字符串getGeofenceTransitionInfo(列出triggeringGeofences){
    ArrayList locationNames=新的ArrayList();
    用于(地理围栏:触发地理围栏){
    add(getLocationName(geofeence.getRequestId());
    System.out.println(“获取操作名”);
    }
    字符串triggeringLocationsString=TextUtils.join(“,”,locationNames);
    返回触发器位置字符串;
    }
    私有字符串getLocationName(字符串键){
    字符串[]strs=key.split(“”);
    字符串locationName=null;
    if(strs!=null&&strs.length==2){
    double lat=double.parseDouble(strs[0]);
    双lng=double.parseDouble(strs[1]);
    locationName=getLocationNameGeocoder(lat,lng);
    }else System.out.println(“nullllllllll”);
    if(locationName!=null){
    返回位置名称;
    }否则{
    返回键;
    }
    }
    脉波重复间隔