【发布时间】:2014-10-07 21:08:32
【问题描述】:
我正在尝试使用后台服务,以便我可以每 30 分钟检查一次应用程序上的新内容,并在有任何新内容时通知用户。问题是该服务似乎根本没有启动。我不完全确定我做错了什么。
我已经按照article 实现了通知服务和这个问题 - Trying to start a service on boot on Android。
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.____.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="com.____.BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service android:name="com.____.NotificationService"/>
</application>
BootReceiver 应该启动服务
public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent startServiceIntent = new Intent(context, NotificationService.class);
context.startService(startServiceIntent);
}
}
NotificationService 服务现在设置为显示简单通知
public class NotificationService extends Service {
private WakeLock mWakeLock;
/**
* Simply return null, since our Service will not be communicating with
* any other components. It just does its work silently.
*/
@Override
public IBinder onBind(Intent intent) {
return null;
}
/**
* This is where we initialize. We call this when onStart/onStartCommand is
* called by the system. We won't do anything with the intent here, and you
* probably won't, either.
*/
private void handleIntent(Intent intent) {
// obtain the wake lock
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My App");
mWakeLock.acquire();
// check the global background data setting
ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
if (cm.getActiveNetworkInfo() == null) {
stopSelf();
return;
}
// do the actual work, in a separate thread
new PollTask().execute();
}
private class PollTask extends AsyncTask<Void, Void, Void> {
/**
* This is where YOU do YOUR work. There's nothing for me to write here
* you have to fill this in. Make your HTTP request(s) or whatever it is
* you have to do to get your updates in here, because this is run in a
* separate thread
*/
@SuppressLint("NewApi") @Override
protected Void doInBackground(Void... params) {
// do stuff!
// get last added date time of offer
// every 60 minutes check for new offers
Notification notification = new Notification.Builder(getApplicationContext())
.setContentText("New Content Available")
.setSmallIcon(R.drawable.ic_launcher)
.setWhen(0)
.build();
return null;
}
/**
* In here you should interpret whatever you fetched in doInBackground
* and push any notifications you need to the status bar, using the
* NotificationManager. I will not cover this here, go check the docs on
* NotificationManager.
*
* What you HAVE to do is call stopSelf() after you've pushed your
* notification(s). This will:
* 1) Kill the service so it doesn't waste precious resources
* 2) Call onDestroy() which will release the wake lock, so the device
* can go to sleep again and save precious battery.
*/
@Override
protected void onPostExecute(Void result) {
// handle your data
stopSelf();
}
}
/**
* This is deprecated, but you have to implement it if you're planning on
* supporting devices with an API level lower than 5 (Android 2.0).
*/
@Override
public void onStart(Intent intent, int startId) {
handleIntent(intent);
}
/**
* This is called on 2.0+ (API level 5 or higher). Returning
* START_NOT_STICKY tells the system to not restart the service if it is
* killed because of poor resource (memory/cpu) conditions.
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
handleIntent(intent);
return START_NOT_STICKY;
}
/**
* In onDestroy() we release our wake lock. This ensures that whenever the
* Service stops (killed for resources, stopSelf() called, etc.), the wake
* lock will be released.
*/
public void onDestroy() {
super.onDestroy();
mWakeLock.release();
}
}
在 BootRecevier 和 NotificationService 中使用断点调试应用程序永远不会触发。也许我误解了后台服务的工作方式。
更新
我发现这个article 关于为什么没有调用 BroadcastRecevier。提到的要点之一是 PendingIntent requestCode 缺失
我已按如下方式更新了 BootRecevier 以测试服务...每 1 分钟调用一次:
@Override
public void onReceive(Context context, Intent intent) {
int minutes = 1;
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, NotificationService.class);
PendingIntent pi = PendingIntent.getService(context, 54321, i, 0);
am.cancel(pi);
if (minutes > 0) {
am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + minutes*60*1000,
minutes*60*1000, pi);
}
}
将 0 更改为“唯一”requestCode54321 以某种方式开始触发服务。问题是当应用程序关闭时服务无法继续工作......不确定这是否完全不同。
更新 2
我更新了 NotificationService 中的doInBackground 方法,使用此example 来显示通知:
@SuppressLint("NewApi") @Override
protected Void doInBackground(Void... params) {
Context mContext = getApplicationContext();
// invoke default notification service
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(mContext);
mBuilder.setContentTitle("[Notification Title]");
mBuilder.setContentText("[Notification Text]");
mBuilder.setTicker(mContext.getString(R.string.app_name));
mBuilder.setSmallIcon(R.drawable.ic_launcher);
Intent resultIntent = new Intent(mContext, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(mContext);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_ONE_SHOT);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, mBuilder.build());
return null;
}
我已经在模拟器上对其进行了测试,即使应用程序关闭,后台服务也能正常工作。但是,在实际设备上测试该应用并没有显示任何通知。
【问题讨论】:
-
您可以尝试手动启动服务,如果您希望它立即启动它。 (当操作系统杀死它时,我有一个粘性消息服务,需要一些时间才能重新启动,但如果我需要立即启动,我会运行此代码) context.startService(new Intent(context, YourService.class));
标签: android notifications background-service