如何在Geofence android中添加后台服务

2024-03-15

我正在尝试创建一个带有监控后台服务的地理围栏。地理围栏创建成功并在应用程序活动打开时工作,但在关闭应用程序地理围栏时不起作用。我现在应该怎么做。我的代码是:

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback,
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener,
    LocationListener {


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_maps);
    // Obtain the SupportMapFragment and get notified when the map is ready to be used.
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);

    ref = FirebaseDatabase.getInstance().getReference("MyLocation");
    geoFire = new GeoFire(ref);
    mVerticalSeekBar = (VerticalSeekBar)findViewById(R.id.verticalSeekBar);

    setUpdateLocation();

}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSION_REQUEST_CODE:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                if (checkPlayService()) {
                    buildGoogleApiClient();
                    createLocationRequest();
                    displayLocation();
                }
            }
            break;
    }
}

private void setUpdateLocation() {
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[]{
                Manifest.permission.ACCESS_COARSE_LOCATION,
                Manifest.permission.ACCESS_FINE_LOCATION
        }, MY_PERMISSION_REQUEST_CODE);
    } else {
        if (checkPlayService()) {
            buildGoogleApiClient();
            createLocationRequest();
            displayLocation();
        }
    }
}

private void displayLocation() {
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }

    mLastLocaiton = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
    if (mLastLocaiton != null) {
        final double latitude = mLastLocaiton.getLatitude();
        final double longitude = mLastLocaiton.getLongitude();

        geoFire.setLocation("You", new GeoLocation(latitude, longitude), new GeoFire.CompletionListener() {
            @Override
            public void onComplete(String key, DatabaseError error) {
                if (mCurrent != null)
                    mCurrent.remove();
                mCurrent = mMap.addMarker(new MarkerOptions()
                        .position(new LatLng(latitude, longitude))
                        .title("You"));
                LatLng coordinate = new LatLng(latitude, longitude);
                CameraUpdate yourLocation = CameraUpdateFactory.newLatLngZoom(coordinate, 12);
                mMap.animateCamera(yourLocation);
            }
        });

        Log.d("MRF", String.format("Your last location was chaged: %f / %f", latitude, longitude));
    } else {
        Log.d("MRF", "Can not get your location.");
    }
}

private void createLocationRequest() {
    mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(UPDATE_INTERVAL);
    mLocationRequest.setFastestInterval(FATEST_INTERVAL);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}

private void buildGoogleApiClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API).build();
    mGoogleApiClient.connect();
}

private boolean checkPlayService() {
    GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
    int result = googleAPI.isGooglePlayServicesAvailable(this);
    if (result != ConnectionResult.SUCCESS) {
        if (googleAPI.isUserResolvableError(result)) {
            googleAPI.getErrorDialog(this, result, PLAY_SERVICE_RESULATION_REQUEST).show();
        } else {
            Toast.makeText(this, "This Device is not supported.", Toast.LENGTH_SHORT).show();
        }
        return false;
    }

    return true;
}

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

    LatLng dangerous_area = new LatLng(23.7424236, 90.3942189);
    mMap.addCircle(new CircleOptions()
            .center(dangerous_area)
            .radius(100)
            .strokeColor(Color.BLUE)
            .fillColor(0x220000FF)
            .strokeWidth(5.0f));

    //add GeoQuery here
    GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(dangerous_area.latitude, dangerous_area.longitude), 0.1f);
    geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
        @Override
        public void onKeyEntered(String key, GeoLocation location) {
            sendNotification("MRF", String.format("%s entered the dangerous area",key));
        }

        @Override
        public void onKeyExited(String key) {
            sendNotification("MRF", String.format("%s exit the dangerous area",key));
        }

        @Override
        public void onKeyMoved(String key, GeoLocation location) {
            Log.d("MOVE", String.format("%s move within the dangerous area [%f/%f]", key, location.latitude, location.longitude));
        }

        @Override
        public void onGeoQueryReady() {

        }

        @Override
        public void onGeoQueryError(DatabaseError error) {
            Log.d("ERROR", ""+error);
        }
    });
}

private void sendNotification(String title, String content) {
    Notification.Builder builder = new Notification.Builder(this)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle(title)
            .setContentText(content);

    NotificationManager manager = (NotificationManager)this.getSystemService(Context.NOTIFICATION_SERVICE);
    Intent intent = new Intent(this, MapsActivity.class);
    PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
    builder.setContentIntent(contentIntent);
    Notification notification = builder.build();
    notification.flags |= Notification.FLAG_AUTO_CANCEL;
    notification.defaults |= Notification.DEFAULT_SOUND;
    manager.notify(new Random().nextInt(), notification);
}

@Override
public void onConnected(@Nullable Bundle bundle) {
    displayLocation();
    startLocationUpdate();
}

private void startLocationUpdate() {
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}

@Override
public void onConnectionSuspended(int i) {
    mGoogleApiClient.connect();
}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

}

@Override
public void onLocationChanged(Location location) {
    mLastLocaiton = location;
    displayLocation();
}

github链接是:https://github.com/Farhad2015/Geofence-GeoFire/blob/master/app/src/main/java/com/mahmud/geotesting/MapsActivity.java https://github.com/Farhad2015/Geofence-GeoFire/blob/master/app/src/main/java/com/mahmud/geotesting/MapsActivity.java

请帮助我创建一个后台服务,用于从后台监控地理围栏。


从 Android Oreo 中,您无法创建长时间运行的服务作为后台服务。所以你必须创建一个前台服务,该服务必须绑定到当前的 Activity

另一个问题是位置更新。当你使用geoQuery在服务内部,您还必须在服务中更新位置。当位置更新触发时,您必须将此更新传递给 Activity,然后只有 UI 可以更新。在我的解决方案中,我使用一个界面来更新 UI。您还可以使用广播侦听器。

当您创建服务并将其绑定到活动时,您可以在服务内使用地理围栏

 public void startService(LatLng latLng, double radius) {
        if (!isServiceRunning) {
            isServiceRunning = true;

        } else {
            Log.e(TAG, "startTimer request for an already running timer");

        }
        if (geoQuery!=null){
            geoQuery.removeAllListeners();
        }
        geoQuery = geoFire.queryAtLocation(new GeoLocation(latLng.latitude, latLng.longitude), 2f);
        geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
            @Override
            public void onKeyEntered(String key, GeoLocation location) {
                sendNotification("MRF", String.format("%s entered the dangerous area", key));
            }

            @Override
            public void onKeyExited(String key) {
                sendNotification("MRF", String.format("%s exit the dangerous area", key));
            }

            @Override
            public void onKeyMoved(String key, GeoLocation location) {
                Log.d("MOVE", String.format("%s move within the dangerous area [%f/%f]", key, location.latitude, location.longitude));
            }

            @Override
            public void onGeoQueryReady() {

            }

            @Override
            public void onGeoQueryError(DatabaseError error) {
                Log.d("ERROR", "" + error);
            }
        });
    }

您可以从您的活动中调用此方法,如下所示

  geoService.startService(dangerous_area,2000);

即使您的应用程序被破坏,这也将起作用。

完整代码如下

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {


    private GoogleMap mMap;
    //Play Service Location
    private static final int MY_PERMISSION_REQUEST_CODE = 7192;
    private static final int PLAY_SERVICE_RESULATION_REQUEST = 300193;

    private Location mLastLocaiton;

    private static int UPDATE_INTERVAL = 5000;
    private static int FATEST_INTERVAL = 3000;
    private static int DISPLACEMENT = 10;


    Marker mCurrent;
    VerticalSeekBar mVerticalSeekBar;
    private static final String TAG = MapsActivity.class.getSimpleName();

    private GeoService geoService;
    private boolean serviceBound;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.



        mVerticalSeekBar = (VerticalSeekBar) findViewById(R.id.verticalSeekBar);
        mVerticalSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                mMap.animateCamera(CameraUpdateFactory.zoomTo(progress), 1500, null);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });



    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSION_REQUEST_CODE:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    if (checkPlayService()) {
                        geoService.buildGoogleApiClient();
                        geoService.createLocationRequest();
                        geoService.displayLocation();
                        geoService.setLocationChangeListener(new GeoService.LocationChangeListener() {
                            @Override
                            public void onLocationChange(Location location) {
                                if (mCurrent != null)
                                    mCurrent.remove();
                                mCurrent = mMap.addMarker(new MarkerOptions()
                                        .position(new LatLng(location.getLatitude(), location.getLongitude()))
                                        .title("You"));
                                LatLng coordinate = new LatLng(location.getLatitude(), location.getLongitude());
                                CameraUpdate yourLocation = CameraUpdateFactory.newLatLngZoom(coordinate, 12);
                                mMap.animateCamera(yourLocation);
                            }
                        });
                    }
                }
                break;
        }
    }

    private void setUpdateLocation() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{
                    Manifest.permission.ACCESS_COARSE_LOCATION,
                    Manifest.permission.ACCESS_FINE_LOCATION
            }, MY_PERMISSION_REQUEST_CODE);
        } else {
            if (checkPlayService()) {
                geoService.buildGoogleApiClient();
                geoService.createLocationRequest();
                geoService.displayLocation();
                geoService.setLocationChangeListener(new GeoService.LocationChangeListener() {
                    @Override
                    public void onLocationChange(Location location) {
                        if (mCurrent != null)
                            mCurrent.remove();
                        mCurrent = mMap.addMarker(new MarkerOptions()
                                .position(new LatLng(location.getLatitude(), location.getLongitude()))
                                .title("You"));
                        LatLng coordinate = new LatLng(location.getLatitude(), location.getLongitude());
                        CameraUpdate yourLocation = CameraUpdateFactory.newLatLngZoom(coordinate, 12);
                        mMap.animateCamera(yourLocation);
                    }
                });
            }
        }
    }


    private boolean checkPlayService() {
        GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
        int result = googleAPI.isGooglePlayServicesAvailable(this);
        if (result != ConnectionResult.SUCCESS) {
            if (googleAPI.isUserResolvableError(result)) {
                googleAPI.getErrorDialog(this, result, PLAY_SERVICE_RESULATION_REQUEST).show();
            } else {
                Toast.makeText(this, "This Device is not supported.", Toast.LENGTH_SHORT).show();
            }
            return false;
        }

        return true;
    }

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

        LatLng dangerous_area = new LatLng(8.5324236, 76.8842189);
        mMap.addCircle(new CircleOptions()
                .center(dangerous_area)
                .radius(2000)
                .strokeColor(Color.BLUE)
                .fillColor(0x220000FF)
                .strokeWidth(5.0f));

        geoService.startService(dangerous_area,2000);


    }


    @Override
    protected void onStart() {
        super.onStart();
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "Starting and binding service");
        }
        Intent i = new Intent(this, GeoService.class);
        startService(i);
        bindService(i, mConnection, 0);

    }

    @Override
    protected void onStop() {
        super.onStop();
        if (serviceBound) {
            // If a timer is active, foreground the service, otherwise kill the service
            if (geoService.isServiceRunning()) {
                geoService.foreground();
            } else {
                stopService(new Intent(this, GeoService.class));
            }
            // Unbind the service
            unbindService(mConnection);
            serviceBound = false;
        }
    }

    /**
     * Callback for service binding, passed to bindService()
     */
    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "Service bound");
            }
            GeoService.RunServiceBinder binder = (GeoService.RunServiceBinder) service;
            geoService = binder.getService();
            serviceBound = true;
            // Ensure the service is not in the foreground when bound
            geoService.background();
            setUpdateLocation();
            SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                    .findFragmentById(R.id.map);
            mapFragment.getMapAsync(MapsActivity.this);

        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "Service disconnect");
            }
            serviceBound = false;
        }
    };


    public static class GeoService extends Service implements GoogleApiClient.ConnectionCallbacks,
            GoogleApiClient.OnConnectionFailedListener,
            LocationListener {
        private LocationRequest mLocationRequest;
        private GoogleApiClient mGoogleApiClient;
        private Location mLastLocation;
        private DatabaseReference ref;
        private GeoFire geoFire;
        private LocationChangeListener mLocationChangeListener;
        private static final String TAG = GeoService.class.getSimpleName();


        // Is the service tracking time?
        private boolean isServiceRunning;

        // Foreground notification id
        private static final int NOTIFICATION_ID = 1;

        // Service binder
        private final IBinder serviceBinder = new RunServiceBinder();
        private GeoQuery geoQuery;

        public class RunServiceBinder extends Binder {
            GeoService getService() {
                return GeoService.this;
            }
        }

        @Override
        public void onCreate() {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "Creating service");
            }
            ref = FirebaseDatabase.getInstance().getReference("MyLocation");
            geoFire = new GeoFire(ref);
            isServiceRunning = false;
        }

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "Starting service");
            }
            return Service.START_STICKY;
        }

        @Override
        public IBinder onBind(Intent intent) {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "Binding service");
            }
            return serviceBinder;
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "Destroying service");
            }
        }

        /**
         * Starts the timer
         */
        public void startService(LatLng latLng, double radius) {
            if (!isServiceRunning) {
                isServiceRunning = true;

            } else {
                Log.e(TAG, "startService request for an already running Service");

            }
            if (geoQuery!=null){
                geoQuery.removeAllListeners();
            }
            geoQuery = geoFire.queryAtLocation(new GeoLocation(latLng.latitude, latLng.longitude), 2f);
            geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
                @Override
                public void onKeyEntered(String key, GeoLocation location) {
                    sendNotification("MRF", String.format("%s entered the dangerous area", key));
                }

                @Override
                public void onKeyExited(String key) {
                    sendNotification("MRF", String.format("%s exit the dangerous area", key));
                }

                @Override
                public void onKeyMoved(String key, GeoLocation location) {
                    Log.d("MOVE", String.format("%s move within the dangerous area [%f/%f]", key, location.latitude, location.longitude));
                }

                @Override
                public void onGeoQueryReady() {

                }

                @Override
                public void onGeoQueryError(DatabaseError error) {
                    Log.d("ERROR", "" + error);
                }
            });
        }

        /**
         * Stops the timer
         */
        public void stopService() {
            if (isServiceRunning) {
                isServiceRunning = false;
                geoQuery.removeAllListeners();
            } else {
                Log.e(TAG, "stopTimer request for a timer that isn't running");
            }
        }

        /**
         * @return whether the service is running
         */
        public boolean isServiceRunning() {
            return isServiceRunning;
        }


        /**
         * Place the service into the foreground
         */
        public void foreground() {
            startForeground(NOTIFICATION_ID, createNotification());
        }

        /**
         * Return the service to the background
         */
        public void background() {
            stopForeground(true);
        }

        /**
         * Creates a notification for placing the service into the foreground
         *
         * @return a notification for interacting with the service when in the foreground
         */
        private Notification createNotification() {
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                    .setContentTitle("Service is Active")
                    .setContentText("Tap to return to the Map")
                    .setSmallIcon(R.mipmap.ic_launcher);

            Intent resultIntent = new Intent(this, MapsActivity.class);
            PendingIntent resultPendingIntent =
                    PendingIntent.getActivity(this, 0, resultIntent,
                            PendingIntent.FLAG_UPDATE_CURRENT);
            builder.setContentIntent(resultPendingIntent);

            return builder.build();
        }

        private void sendNotification(String title, String content) {
            Notification.Builder builder = new Notification.Builder(this)
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setContentTitle(title)
                    .setContentText(content);

            NotificationManager manager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
            Intent intent = new Intent(this, MapsActivity.class);
            PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
            builder.setContentIntent(contentIntent);
            Notification notification = builder.build();
            notification.flags |= Notification.FLAG_AUTO_CANCEL;
            notification.defaults |= Notification.DEFAULT_SOUND;
            manager.notify(new Random().nextInt(), notification);
        }

        @Override
        public void onConnected(@Nullable Bundle bundle) {
            displayLocation();
            startLocationUpdate();
        }

        private void startLocationUpdate() {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                    ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                return;
            }
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
        }

        @Override
        public void onConnectionSuspended(int i) {
            mGoogleApiClient.connect();
        }

        @Override
        public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

        }

        @Override
        public void onLocationChanged(Location location) {
            mLastLocation = location;
            displayLocation();
        }

        interface LocationChangeListener {
            void onLocationChange(Location location);
        }

        private void createLocationRequest() {
            mLocationRequest = new LocationRequest();
            mLocationRequest.setInterval(UPDATE_INTERVAL);
            mLocationRequest.setFastestInterval(FATEST_INTERVAL);
            mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
            mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
        }

        private void buildGoogleApiClient() {
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API).build();
            mGoogleApiClient.connect();
        }

        private void displayLocation() {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                    ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                return;
            }

            mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
            if (mLastLocation != null) {
                final double latitude = mLastLocation.getLatitude();
                final double longitude = mLastLocation.getLongitude();

                geoFire.setLocation("You", new GeoLocation(latitude, longitude), new GeoFire.CompletionListener() {
                    @Override
                    public void onComplete(String key, DatabaseError error) {
                        if (mLocationChangeListener!=null) {
                            mLocationChangeListener.onLocationChange(mLastLocation);
                        }
                    }
                });

                Log.d("MRF", String.format("Your last location was chaged: %f / %f", latitude, longitude));
            } else {
                Log.d("MRF", "Can not get your location.");
            }
        }

        public void setLocationChangeListener(LocationChangeListener mLocationChangeListener) {
            this.mLocationChangeListener = mLocationChangeListener;
        }
    }

}

不要忘记将服务添加到清单中

  <service android:name=".MapsActivity$GeoService" />

完整源代码github.com/vinayakb73/GeoFence-GeoFire http://github.com/vinayakb73/GeoFence-GeoFire

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在Geofence android中添加后台服务 的相关文章

  • Android EditText 和 addTextChangedListener

    我目前正在将数据库管理器移植到 Android 由于性能原因 我喜欢 仅更新已修改的属性 我尝试使用 addTextChangedListener 执行此操作 以便将修改后的条目添加到列表中 但我的程序从未输入其任何方法 EditText
  • 用于 Kotlin 中单元测试的 BuildConfigField 模拟

    我正在尝试尽可能多地涵盖Kotlin Android 库我遇到了有关自定义 BuildConfig 变量的问题 更广为人知的是buildConfigField 我想模拟这个变量来测试两者true and false values 从 Gra
  • 通过代码在创建时突出显示 ListView 项目

    我想在创建 listView 时突出显示 ListView 的第一行 0 我尝试了不同的方法 就像您在注释代码中看到的那样 但没有任何效果 这很奇怪 因为 OnItemClickListener 中的突出显示工作正常 它通过 xml 选择器
  • VOIP通话录音

    我正在开发一个在 android 中录制 VOIP 通话的项目 我没有找到任何解决方案 有很多应用程序支持手机上的 VOIP 录音 我找不到任何教程和帮助 立方体通话记录器 https play google com store apps
  • 自动删除 Firebase 通知

    我有一个问题 我都读过让通知在 5 分钟后消失 https stackoverflow com questions 15648699 make notification disappear after 5 minutes and 几秒钟后清
  • 更改语言 Flutter 的按钮

    我正在 Flutter 中构建一个应用程序 到目前为止 我正在使用 JSON 国际化 其中应用程序的语言基于用户手机中默认的语言 它工作得很好 但我想给用户有机会在不更改手机系统语言设置的情况下更改语言 只需单击按钮 然后应用程序即可更改语
  • java.lang.IllegalAccessError:预验证类中的类引用在运行测试项目时解析为意外实现?

    在实施项目工作正常之后 我使用第三方库 zxing 实施了项目 然后在我编写了一个测试项目对我的项目进行单元测试之后 运行测试项目后 主项目 类及其方法没有给出任何信息错误 但如果在主项目的该方法中使用任何 zxing 框架类 则会在运行时
  • 使用 DataBinding 测试片段时膨胀类 Fragment 时出错

    有人可以帮我解决这个问题吗 在我的测试中 我想检查登录按钮是否显示在起始页上 今天我已经为这个错误苦苦挣扎了一段时间 我不知道应该如何解决它 我在这里错过了什么 也许这个问题与这个问题有些相似 Espresso 测试失败 并显示 java
  • 什么是 Android 测试协调器?

    谷歌最近发布了Android测试支持库1 0 读完后overview https android developers googleblog com 2017 07 android testing support library 10 is
  • Android 和 Google 地图内部片段以及其他控件和 viewpager

    我是android编程新手 我有一个带有 3 个页面 片段 的小应用程序 使用 pageradapter 和 viewpager 在它们之间滑动 其中一个页面包含复选框 和其他控件 和地图 我的问题是程序在启动时崩溃 Fragment co
  • 如何在同一设备上运行的 Android 应用程序之间传输文件?

    我正在编写一个与 RESTful 服务交互的 Android 应用程序 该 Web 服务本质上是一个文件系统 并提供元数据以及对文件的 CRUD 访问 我的应用程序检索元数据 并通过ContentProvider 我需要添加与我的应用程序在
  • Android Google Map V2:如何在单击另一个标记时更改先前单击的标记的图标

    更新 我通过添加 previousMarker 对象解决了性能问题 因此 只有先前单击的标记将被删除并替换为默认图标 但是 当我单击标记时 信息窗口仍然不显示 我有一个地图视图并在上面设置了一些标记 我想要的是 当我单击一个标记时 它将其图
  • 使用 Proguard 通过 Dropbox.com 库混淆 Android 应用程序

    我刚刚创建了一个需要 Dropbox com API 库的 Android 应用程序 我现在尝试在 发布 模式下构建应用程序 并希望在代码上运行混淆器以对其进行混淆 但是 每当我尝试运行 Proguard 时 都会收到以下错误 Progua
  • Expresso 的 Android 测试首选项片段

    我在通过 Expresso 测试我的代码时遇到问题 我写了这段代码 public class SettingsActivity extends Activity Override protected void onCreate Bundle
  • 文本视图不显示全文

    我正在使用 TableLayout 和 TableRow 创建一个简单的布局 其中包含两个 TextView 这是代码的一部分
  • Android 中 Activity 之间的 3D 动画

    How to create animation between two Activity look like As Screen shot in android 搜索jazzyviewpager 这是link https github co
  • 在数组列表中过滤 Filterable 不取消之前的过滤

    我看过过滤器方法文档 其中显示调用过滤器会取消所有先前未执行的过滤请求 并发布一个稍后将执行的新过滤请求 但我收到的实际回调有些不同 在我的实现中 它不会取消先前的过滤器请求并调用publishResults 最近一次搜索条件后的上一次搜索
  • 如何从DataSource.Factory获取数据

    我必须调用此方法才能获取所有人员 我根本无法修改这个方法 Query SELECT FROM PERSON TABLE ORDER BY NAME DESC abstract fun getElements DataSource Facto
  • Android 的代码覆盖率[重复]

    这个问题在这里已经有答案了 可能的重复 Android测试代码覆盖率 Eclipse https stackoverflow com questions 3282702 android test code coverage eclipse
  • 如何用LoaderManager自动重新查询

    我有一个应用程序显示来自 SQLite DB 的数据 并且数据不断变化 所以显然 我认为我应该使用 LoaderManager 来显示数据 我读过一些关于将 LoaderManager 与 SQLite 结合使用的内容 然后看到了亚历克斯

随机推荐

  • 如何发现我创建的物化视图的基础查询?

    我在 Postgres 9 3 中创建了一个物化视图 但此后我丢失了创建它的底层 SELECT 查询 我想删除物化视图 重写查询以包含更多数据 然后创建一个同名但具有新基础查询的物化视图 Just SELECT pg get viewdef
  • 创建键绑定以运行上一个或最后一个 shell 命令

    我经常想快速重新运行我使用的最后一个 shell 命令 我知道您可以将焦点转移到终端 向上箭头并输入 但我认为一定有比这三个步骤更好的方法 The sendSequencevscode 中的命令变得越来越强大 因此我寻找一种方法来创建一个可
  • 有没有一种简单的方法可以将 vulture 与 django 一起使用?

    我正在尝试清理 django 中一些混乱的遗留代码 Vulture http pypi python org pypi vulture看起来是一个不错的选择 但它似乎不知道如何查找 urls py 引用的视图函数 这并不奇怪 因为大多数函数
  • HTML 中的 valign 与 text-align

    我无法通过以下代码找出 HTML 中 valign 与 text align 之间的区别 table width 500 border 0 tr td style background color FFA500 h1 Main Title
  • 在解组操作期间将 nil="true" 转换为 null

    我从服务器接收 XML 该服务器的架构将几乎每个元素指定为
  • Java:jsr166y Phaser 的教程/说明

    这个问题 https stackoverflow com questions 1148125 resources on the upcoming fork join framework两年前被问到 但它提到的资源要么不是很有帮助 恕我直言
  • kivy 应用程序内的一个简单网页作为小部件

    我想在 ubuntu 64 位上运行的 kivy 应用程序中有一个 Web 视图 我查看了网络 浏览了 kivy 的文档并在 StackOverflow 上搜索答案 但我找不到任何可以完成我的工作的东西 一个简单的网页需要在 kivy 应用
  • 可以检测元素的样式是否只是浏览器默认样式还是由样式表或内联样式设置吗?

    我的 javascript 包含在 X 的网站中 但我对她的网站或她包含它的位置没有任何其他控制权 如果她的造型 element 我想不管它 但如果她没有 我有一个样式表 我会注入 有什么办法可以检测她是否有造型吗 检查它的高度是 0 还是
  • 如何用Go实现BitSet?

    我在Go中没有找到BitSet包 所以我尝试实现它 我想使用 uint64 数组来存储这些位 我需要分配 uint64 数组的位数 使用 Java 我可以定义一个采用整数的构造函数 虽然 Go 不提供构造函数 但我如何正确初始化 当用户调用
  • 交换 css 字体时是否会发出 js 事件?

    我可以判断字体何时已成功 或以其他方式 加载 然后使用 JS 进行操作吗 Context 我正在使用 playwright 打印一系列文档 我目前正在加载这些字体https fonts googleapis com css2 family
  • 理解 Java 中抽象类的用途

    假设我有两个类 A和B A类被定义为抽象类 而B类扩展了这个抽象类 最后我测试结果 这两个类都是同一个包的一部分 public abstract class A protected abstract void method1 protect
  • 游标与 While 循环 - SQL Server

    假设我在数据库 本例中为 SQL Server 2008 中有一堆可用于创建方程的行 OperationID EquationID Operation Amount Order 1 1 12 1 2 1 12 2 3 2 2
  • Kubernetes 将 env 变量传递给“kubectl create”

    我需要将动态环境变量传递给kubectl create 像这样的东西 kubectl create f app yaml Target prod 基于Target的代码部署在不同的服务器上 如果您想避免安装第 3 方插件 则可以使用 sed
  • 如何使用 Language-Ext 将 Task> 绑定到 Either<>

    我有可以请求数据库中保存的卡列表的设备 例如移动电话 支付终端等 为了安全起见 设备需要对自己进行授权 并在 JWT 令牌中提供其序列号 如果其中任何一项不匹配 我们将拒绝该请求 感谢最近对相关问题的大量帮助 我现在有两种在类似场景中使用的
  • 从 Facebook 页面提取公共帖子,无需 API/APP 密钥/令牌/秘密

    提前澄清一下 我没有 Facebook 帐户 也无意创建一个帐户 另外 我想要实现的目标在我的国家和美国是完全合法的 我不想使用 Facebook API 来获取 Facebook 页面的最新时间线帖子 而是直接向页面 URL 发送获取请求
  • 当我在 ASP.NET 中组合 Bearer Token 和 Cookie 身份验证时,出现 401

    我需要结合令牌和 cookie 来授权 wepapi 项目中的请求 我添加了 Cookie 和 Jwt 来验证请求 在更改 DefaultPolicy 之前 我可以获得我的声明 信息 但更改后我得到 401 这是我的 Program cs
  • 在 R 中,变量与基本 R 函数同名到底有什么问题?

    使用在基本 R 中具有相同名称的函数的变量名称似乎通常被认为是不好的编程习惯 例如 很容易写成 data lt data frame df lt data frame 现在 函数data函数加载数据集df计算 f 密度函数 同样 也很容易写
  • Jupyter Notebook 将默认文件夹设置为根目录

    我在 Windows 7 上使用 Jupyter Notebook 我想将默认文件夹设置为D 目前 我的 jupyter notebook config py 中有以下行 c NotebookApp notebook dir D 当我打开
  • 如何在Python中读取QLineEdit中的文本?

    我为我的插件创建了一个带有 3 个按钮的启动 GUI 这非常有效 如果我单击其中一个按钮 就会启动特定操作 到目前为止这有效 如果我单击其中一个按钮 则会出现一个带有两个按钮 确定 和 取消 的新 GUI 以及一个行编辑 如果我按下 取消
  • 如何在Geofence android中添加后台服务

    我正在尝试创建一个带有监控后台服务的地理围栏 地理围栏创建成功并在应用程序活动打开时工作 但在关闭应用程序地理围栏时不起作用 我现在应该怎么做 我的代码是 public class MapsActivity extends Fragment