android - 如何解决 GPS 在后台 android Pie 中自动关闭?

标签 android gps location

我正在尝试在 android 中使用 GPS 获取坐标。我已成功在前台获取位置,但每当我将应用程序置于后台时,GPS 标志就会消失,并且它会在后台停止定位点。 我使用了不同版本的 android,一些定位位置点(低于 8.0),有些则没有(Pie)。

如何在 Pie 中继续在后台运行 GPS。我尝试了不同的 SO 答案,但没有得到解决方案。

我正在使用服务在后台运行应用程序并使用广播接收器获取坐标。但我在 Pie 版本中没有得到积分。

Here's my MainActivity.java

public class MainActivity extends AppCompatActivity {

    private LocationManager locationManager;
    private LocationListener locationListener;
    private double latitude, longitude;
    BroadcastReceiver broadcastReceiver;

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

        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        /*inflating layout*/
        riderFirstName = findViewById(R.id.rider_fName);
        riderLastName = findViewById(R.id.rider_lName);
        riderNote = findViewById(R.id.note);
        logout = findViewById(R.id.logout);     

        if (!runtime_permissions()) {
            Intent i = new Intent(getApplicationContext(), GPS_Service.class);
            startService(i);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        if (broadcastReceiver==null){
            broadcastReceiver=new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {

                    double lat = (double) intent.getExtras().get("latitude");
                    double lng= (double) intent.getExtras().get("longitude");
                    Log.i("lat", String.valueOf(lat));
                    Log.i("lang", String.valueOf(lng));
                    Log.i("lang", String.valueOf(RiderID));

                }
            };
        }
        registerReceiver(broadcastReceiver, new IntentFilter("location_update"));
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (broadcastReceiver!=null)
            unregisterReceiver(broadcastReceiver);
    }

    private boolean runtime_permissions() {
        if (Build.VERSION.SDK_INT >= 23 && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 100);

            return true;
        }
        return false;
    }


    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 100) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
                Intent i = new Intent(getApplicationContext(), GPS_Service.class);
                startService(i);
            } else {
                runtime_permissions();
            }
        }
    }

}

Here's my Service class

public class GPS_Service extends Service {
    PowerManager.WakeLock wakeLock;

    private LocationListener listener;
    private LocationManager locationManager;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @SuppressLint("InvalidWakeLockTag")
    @Override
    public void onCreate() {

        listener = new LocationListener() {
            @Override
            public void onLocationChanged(Location location) {
                Intent i = new Intent("location_update");
                i.putExtra("latitude",  location.getLatitude());
                i.putExtra("longitude", location.getLongitude());

                sendBroadcast(i);
            }

            @Override
            public void onStatusChanged(String s, int i, Bundle bundle) {

            }

            @Override
            public void onProviderEnabled(String s) {

            }

            @Override
            public void onProviderDisabled(String s) {
                Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(i);
            }

        };

        locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);

        //noinspection MissingPermission
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, CommonObjects.DELAY_LOCATION, 0, listener);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if(locationManager != null){
            //noinspection MissingPermission
            locationManager.removeUpdates(listener);
        }
    }
}

Here's Manifest

 <!-- my permissions -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />

最佳答案

通过使用 startForegroundService() 而不是 startService() 我得到了解决我的问题(在后台获取 GPS 位置)的奥利奥 (8.0) 及更高版本。

为了实现,我们必须在 Manifest 中添加一个 Foreground 权限,并在 Service 类中添加一个 startForeground(); 方法,如下所示:

这是我更新的 MianActivity.java 代码

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

        ...    

        if (!runtime_permissions()) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
        {
            Intent serviceIntent = new Intent(context, YourService.class);
            ContextCompat.startForegroundService(context, serviceIntent );
        }
        else
        {
            context.startService(new Intent(context, YourService.class));
        }
        }
    }

更新了我的服务类

@SuppressLint("InvalidWakeLockTag")
    @Override
    public void onCreate() {

     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
            startMyOwnForeground();
        else
            startForeground(1, new Notification());

     ...

}

private void startMyOwnForeground(){
        String NOTIFICATION_CHANNEL_ID = "com.example.simpleapp";
        String channelName = "My Background Service";
        NotificationChannel chan = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_NONE);
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            chan.setLightColor(Color.BLUE);
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
        }
        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        assert manager != null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            manager.createNotificationChannel(chan);
        }

        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
        Notification notification = notificationBuilder.setOngoing(true)
                .setContentTitle("App is running in background")
                .setPriority(NotificationManager.IMPORTANCE_MIN)
                .setCategory(Notification.CATEGORY_SERVICE)
                .build();
        startForeground(2, notification);
    }

更新 list 许可

    ...
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

关于android - 如何解决 GPS 在后台 android Pie 中自动关闭?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56413488/

相关文章:

android - 为android中的每种风格替换一个XML文件

android - html 5 canvas 硬件是否在 android chrome beta 上加速?

mysql - 使用 WHERE 子句查找经度和纬度距离范围内的 POI

php - 如何使用 php 将 GPS 坐标转换为完整地址?

algorithm - 表示位置和基于接近度查询的有效方法?

android - 如何在 PagerAdapter 的 instantiateItem 方法中使用 AsyncTask

java - Android : java. lang.SecurityException:权限拒绝:

Android手机在执行我自己开发的应用程序时重启

webpack 构建到文件位置

Android ICS 网络位置未更新