我正在尝试为我正在使用的 Android 应用程序添加后台服务。我关注了this guide用于添加服务并在主 Activity 被销毁时让它在后台重新启动。这没有像指南中显示的那样工作,因为(我认为)我需要使广播明确(描述 here )。我试图通过将其添加到我的服务的构造函数中来做到这一点:
applicationContext.registerReceiver(
new LocationSyncServiceRestarterBroadcastReceiver(),
new IntentFilter("com.company.AppName.RestartLocationSyncService")
);
添加这个之后,当我关闭应用程序时,它不再抛出广播失败错误,但它似乎也没有运行 LocationSyncServiceRestarterBroadcastReceiver.onReceive
(或者它只是没有出现在日志中).
这就是我创建后台服务的方式(在 MainActivity
中):
private void startLocationSyncService() {
ctx = this;
mLocationSyncService = new LocationSyncService(getCtx());
mLocationSyncServiceIntent = new Intent(getCtx(), mLocationSyncService.getClass());
if (!isServiceRunning(mLocationSyncService.getClass())) {
startService(mLocationSyncServiceIntent);
}
}
private boolean isServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
Log.i ("isMyServiceRunning?", true+"");
return true;
}
}
Log.i ("isMyServiceRunning?", false+"");
return false;
}
这是我的后台服务:
package com.company.AppName;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
public class LocationSyncService extends Service {
private static final String TAG = "LocationSyncService";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 1000;
private static final float LOCATION_DISTANCE = 10f;
LocationListener[] mLocationListeners = new LocationListener[] {
new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.NETWORK_PROVIDER)
};
public LocationSyncService() {}
public LocationSyncService(Context applicationContext) {
super();
Log.i(TAG, "created");
applicationContext.registerReceiver(
new LocationSyncServiceRestarterBroadcastReceiver(),
new IntentFilter("com.company.AppName.RestartLocationSyncService")
);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind");
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
Log.i(TAG, "onStartCommand");
return START_STICKY;
}
@Override
public void onCreate()
{
Log.e(TAG, "onCreate");
initializeLocationManager();
try {
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[1]);
} catch (java.lang.SecurityException ex) {
Log.e(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.e(TAG, "network provider does not exist, " + ex.getMessage());
}
try {
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[0]);
} catch (java.lang.SecurityException ex) {
Log.e(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.e(TAG, "gps provider does not exist " + ex.getMessage());
}
}
private void initializeLocationManager() {
Log.i(TAG, "initializeLocationManager");
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy");
Intent broadcastIntent = new Intent("com.company.AppName.RestartLocationSyncService");
sendBroadcast(broadcastIntent);
}
private class LocationListener implements android.location.LocationListener
{
Location mLastLocation;
public LocationListener(String provider)
{
Log.i(TAG, "LocationListener " + provider);
mLastLocation = new Location(provider);
}
@Override
public void onLocationChanged(Location location)
{
Log.i(TAG, "onLocationChanged: " + location);
mLastLocation.set(location);
}
@Override
public void onProviderDisabled(String provider)
{
Log.i(TAG, "onProviderDisabled: " + provider);
}
@Override
public void onProviderEnabled(String provider)
{
Log.i(TAG, "onProviderEnabled: " + provider);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
Log.i(TAG, "onStatusChanged: " + provider);
}
}
}
以及应该重启服务的广播接收器:
package com.company.AppName;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class LocationSyncServiceRestarterBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "RestarterBcastReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "----- onReceive!!!");
context.startService(new Intent(context, LocationSyncService.class));
}
}
还有我的AndroidManifest.xml
:
<?xml version='1.0' encoding='utf-8'?>
<manifest android:hardwareAccelerated="true" android:versionCode="10000" android:versionName="1.0.0" package="com.company.AppName" xmlns:android="http://schemas.android.com/apk/res/android">
<supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true" />
<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" />
<application android:hardwareAccelerated="true" android:icon="@mipmap/icon" android:label="@string/app_name" android:supportsRtl="true">
<activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:label="@string/activity_name" android:launchMode="singleTop" android:name="MainActivity" android:screenOrientation="portrait" android:theme="@android:style/Theme.DeviceDefault.NoActionBar" android:windowSoftInputMode="adjustResize">
<intent-filter android:label="@string/launcher_name">
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider android:authorities="${applicationId}.provider" android:exported="false" android:grantUriPermissions="true" android:name="org.apache.cordova.camera.FileProvider">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/camera_provider_paths" />
</provider>
<service android:enabled="true" android:name="com.company.AppName.LocationSyncService" />
<receiver android:enabled="true" android:exported="true" android:label="RestartLocationSyncServiceWhenStopped" android:name="com.company.AppName.LocationSyncServiceRestarterBroadcastReceiver">
<intent-filter>
<action android:name="com.company.AppName.RestartLocationSyncService" />
</intent-filter>
</receiver>
</application>
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="26" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>
最佳答案
解决方案是在从服务的 onDestroy
方法发送到广播接收器的 Intent 上调用 setComponent
:
@Override
public void onDestroy() {
super.onDestroy();
Intent broadcastIntent = new Intent("com.company.AppName.RestartLocationSyncService");
broadcastIntent.setComponent(new ComponentName("com.company.AppName", "com.company.AppName.LocationSyncServiceRestarterBroadcastReceiver"));
sendBroadcast(broadcastIntent);
}
关于java - Android 广播接收器没有接收到显式广播?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52102868/