调用了Android广播接收器但未启动前台服务

问题描述

我设置了广播接收器,以便在重新启动后重新启动前台服务。

我有两个设备,它可以在Meizu M1 note (android 5.1)上运行,但是不能在Samsung A8 (android 9)上运行。在Oreo之后的限制中寻找原因,似乎还可以,但以防万一https://developer.android.com/about/versions/oreo/background.html

在第二个广播接收器上呼叫,但是重新启动后服务未启动。

服务跟踪位置,并将startForeground()Notification一起使用以进行正确的工作。 还尝试添加Worker以便在重新启动后重新启动服务,但此后似乎缺少工作。

请给我任何建议,以使我的收信人无法运行服务。

谢谢。

清单:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.tracker">

    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <application
        android:name=".ui.di.App"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:isolatedProcess="true"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <receiver android:name="com.example.tracker.ui.broadcast.ServiceRestart">
            <intent-filter>
                <action android:name="restartService" />
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.intent.action.ACTION_BOOT_COMPLETED" />
                <action android:name="android.intent.action.QUICKBOOT_POWERON" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>

        <service
            android:name="com.example.tracker.ui.service.TrackerService"
            android:enabled="true" />

        <service
            android:name="com.example.tracker.ui.worker.RestartIntentService"
            android:enabled="true" />


        <activity android:name=".ui.screen.main.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>

</manifest>

收件人:

public class ServiceRestart extends BroadcastReceiver {

    @Override
    public void onReceive(Context context,Intent intent) {
        Log.i("Broadcast Listened","Service tried to stop");
        Toast.makeText(context,"Broadcast: ServiceRestart launched " + intent.getAction(),Toast.LENGTH_LONG).show();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            context.startForegroundService(new Intent(context,TrackerService.class));
        } else {
            context.startService(new Intent(context,TrackerService.class));
        }
    }
}

服务:

public class TrackerService extends Service implements LocationListener {

    public static final String TAG = "TrackerService";

    private static final int PROCESS_ID = 1024;

    private static final int INTERVAL = 120; //seconds

    private ConnectivityManager connectivityManager;

    private PeriodicWorkRequest workRequest;
    private PeriodicWorkRequest restartTrackerRequest;

    private DbFirebaseModel dbFirebaseModel = new DbFirebaseModel();

    private ServiceHandler mServiceHandler;

    private static final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message message) {
        }
    }

    public void onCreate() {
        super.onCreate();

        HandlerThread mHandlerThread = new HandlerThread("TrackerService.HandlerThread");
        mHandlerThread.start();

        mServiceHandler = new ServiceHandler(mHandlerThread.getLooper());
    }

    public TrackerService() {
        super();
    }
    
    @Override
    public int onStartCommand(Intent intent,int flags,int startId) {
        super.onStartCommand(intent,flags,startId);

        addNotificationAndStartForeground();

        addWorkers();

        mServiceHandler.post(() -> {
            connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
            runLocationTransfer();
        });

        Log.d(TAG,"===== SERVICE START");

        return START_STICKY;
    }

    private void addWorkers() {

        workRequest = new PeriodicWorkRequest.Builder(
            FirebaseWorker.class,15,TimeUnit.MINUTES,2,TimeUnit.MINUTES)
            .build();
        WorkManager.getInstance(this).enqueueUniquePeriodicWork(
            FirebaseWorker.TAG,ExistingPeriodicWorkPolicy.REPLACE,workRequest);

        restartTrackerRequest = new PeriodicWorkRequest.Builder(
            TrackerRestartWorker.class,TimeUnit.MINUTES
        ).build();
        WorkManager.getInstance(this).enqueueUniquePeriodicWork(
            TrackerRestartWorker.TAG,restartTrackerRequest);

    }

    private void addNotificationAndStartForeground() {
        String name = getString(R.string.app_name);
        String description = "Service running...";
        PendingIntent pendingIntent = PendingIntent.getActivity(this,new Intent(this,MainActivity.class),0);

        Notification.Builder notificationBuilder;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                Integer.toString(PROCESS_ID),"Tracker",NotificationManager.IMPORTANCE_HIGH);
            channel.setDescription("Notify me when location tracking");

            NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.createNotificationChannel(channel);

            notificationBuilder = new Notification.Builder(this,Integer.toString(PROCESS_ID));
            notificationBuilder.setContentTitle(name)
                .setContentText(description)
                .setSmallIcon(R.drawable.ic_launcher_background)
                .setContentIntent(pendingIntent);

            notificationManager.notify(PROCESS_ID,notificationBuilder.build());
        } else {
            notificationBuilder = new Notification.Builder(this);
            notificationBuilder.setContentTitle(name)
                .setContentText(description)
                .setSmallIcon(R.drawable.ic_launcher_background)
                .setContentIntent(pendingIntent);
        }

        startForeground(PROCESS_ID,notificationBuilder.build());
    }

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

        Log.d(TAG,"===== SERVICE STOP");

        if (FirebaseAuth.getInstance().getCurrentUser() == null) {
            WorkManager.getInstance(this).cancelWorkById(workRequest.getId());
            WorkManager.getInstance(this).cancelWorkById(restartTrackerRequest.getId());
            Log.d(TAG,"===== WORKERS STOP");
        }
    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        Log.d(TAG,"TASK REMOVED");
        Toast.makeText(this,"LOCATION TASK REMOVED",Toast.LENGTH_SHORT).show();

        super.onTaskRemoved(rootIntent);
    }

    private void runLocationTransfer() {

        LocationRequest locationRequest = new LocationRequest();
        locationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER);

        locationRequest.setInterval(INTERVAL * 1000);
        locationRequest.setFastestInterval(INTERVAL * 1000);

        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
        builder.addLocationRequest(locationRequest);
        LocationSettingsRequest locationSettingsRequest = builder.build();

        SettingsClient settingsClient = LocationServices.getSettingsClient(this);
        settingsClient.checkLocationSettings(locationSettingsRequest);

        try {
            getFusedLocationProviderClient(this).requestLocationUpdates(locationRequest,new LocationCallback() {
                    @Override
                    public void onLocationResult(LocationResult locationResult) {
                        onLocationChanged(locationResult.getLastLocation());
                    }
                },Looper.myLooper());

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


    @Override
    public void onLocationChanged(@NonNull Location location) {

        if (FirebaseAuth.getInstance().getCurrentUser() == null) {
            stopSelf();
            Log.d(TAG,"====== SERVICE STOPPED by itself");
        } else if (connectivityManager.getActiveNetworkInfo() != null
            && connectivityManager.getActiveNetworkInfo().isConnected()) {

            dbFirebaseModel.saveLocation(location);

            // test using sound notifications
            try {
                Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
                Ringtone r = RingtoneManager.getRingtone(getApplicationContext(),notification);
                r.play();
            } catch (Exception e) {
                e.printStackTrace();
            }
            Toast.makeText(this,"LOCATION ------ LATITUDE: " + location.getLatitude() + " LONGITUDE: " + location.getLongitude(),Toast.LENGTH_SHORT).show();

        } else {
            saveToLocalStorage(location);
        }
    }


    private void saveToLocalStorage(Location location) {
        Hawk.init(this).build();

        String userId = Objects.requireNonNull(
            FirebaseAuth.getInstance().getCurrentUser()
        ).getUid();

        LocationData locationData = new LocationData(userId,location);

        long count = 0;
        if (Hawk.count() > count) {
            count = Hawk.count();
        }

        while (Hawk.contains(String.valueOf(count))) {
            count++;
        }

        Hawk.put(String.valueOf(count),locationData);

        Log.d(TAG,"HAWK /// Saved to local storage. COUNT = " + Hawk.count());
    }
}

解决方法

以下步骤可以帮助我解决问题:

  1. 删除并重新安装应用

  2. 根据此更改manifest

     <receiver android:name="com.foxminded.tracker.ui.broadcast.ServiceRestart"
     android:exported="true"
     android:enabled="true">
     <intent-filter>
         <action android:name="restartService" />
         <action android:name="android.intent.action.BOOT_COMPLETED" />
         <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
    
         <category android:name="android.intent.category.DEFAULT" />
     </intent-filter>
    

此处添加了"android.intent.action.LOCKED_BOOT_COMPLETED"android:exported="true" android:enabled="true"

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...