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

Android broadcast reciever called but doesn't starts foreground service

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

我有两台设备,可以在 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, 15, TimeUnit.MINUTES, 2, TimeUnit.MINUTES
        ).build();
        WorkManager.getInstance(this).enqueueUniquePeriodicWork(
            TrackerRestartWorker.TAG,
            ExistingPeriodicWorkPolicy.REPLACE,
            restartTrackerRequest);

    }

    private void addNotificationAndStartForeground() {
        String name = getString(R.string.app_name);
        String description = "Service running...";
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, 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"