Sercvice作为android中的四大组件之一,主要用来执行后台耗时任务,比如上传大文件、轮询服务器消息、间断向服务器发送数据、应用处于后台运行时向用户推送通知等等,使用场景多样,但是Service跟Activity一样,也有它的代码模板,这里给出通过StartService启动发送通知的方式的Service代码模板,便于快速开发。
通知已经适配了android8.0版本,这里顺便提一下由于通知在8.0版本android源码改动比较大,提出了一种channel的方式来管理通知,所以当项目的targetVersion>=26的时候需要做版本适配,并手动在设置的通知管理中心内打开通道,才能看到效果,channel通道默认是关闭的。
这里就直接贴上代码了:
public class MessgeService extends Service {
private static final Class[] mStartForegroundSignature = new Class[]{
int.class, Notification.class};
private static final Class[] mStopForegroundSignature = new Class[]{boolean.class};
private NotificationManager mNM;
private Method mStartForeground;
private Method mStopForeground;
private Object[] mStartForegroundArgs = new Object[2];
private Object[] mStopForegroundArgs = new Object[1];
private Uri sound;
private Uri soundDefault;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
mNM = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
sound = Uri.parse("android.resource://" + getPackageName() + "/raw/alarm_voice");
try {
mStartForeground = MessgeService.class.getMethod("startForeground",
mStartForegroundSignature);
mStopForeground = MessgeService.class.getMethod("stopForeground",
mStopForegroundSignature);
} catch (NoSuchMethodException e) {
mStartForeground = mStopForeground = null;
}
// 我们并不需要为 notification.flags 设置 FLAG_ONGOING_EVENT,因为
// 前台服务的 notification.flags 总是默认包含了那个标志位
Notification notification = new Notification();
// 注意使用 startForeground ,id 为 0 将不会显示 notification,1显示
startForegroundCompat(0, notification);
new Thread(r).start();
}
private Runnable r = new Runnable() {
@Override
public void run() {
while (true) {
handler.sendEmptyMessage(0);
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
@Override
public void onDestroy() {
super.onDestroy();
stopForegroundCompat(1);
}
// 以兼容性方式开始前台服务
private void startForegroundCompat(int id, Notification n) {
if (mStartForeground != null) {
mStartForegroundArgs[0] = id;
mStartForegroundArgs[1] = n;
try {
mStartForeground.invoke(this, mStartForegroundArgs);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return;
}
mNM.notify(id, n);
}
// 以兼容性方式停止前台服务
private void stopForegroundCompat(int id) {
if (mStopForeground != null) {
mStopForegroundArgs[0] = Boolean.TRUE;
try {
mStopForeground.invoke(this, mStopForegroundArgs);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return;
}
// 在 setForeground 之前调用 cancel,因为我们有可能在取消前台服务之后
// 的那一瞬间被kill掉。这个时候 notification 便永远不会从通知一栏移除
mNM.cancel(id);
}
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
getUnreadMessage();
}
};
/**
* 读取未读消息的数量.
*/
private void getUnreadMessage() {
new OkHttpClientManager()
.setUrl(MethodConstants.Messge.UNREAD_MESSAGE)
.setOnNetWorkReponse(onNetworkResponse)
.setIngnore(false)
.builder();
}
OkHttpClientManager.OnNetworkResponse onNetworkResponse = new OkHttpClientManager.OnNetworkResponse() {
@Override
public void onNetworkResponse(String result) {
try {
JSONObject json = new JSONObject(result);
int messgeCount = json.optInt("unreadMessageCount");
AppApplication.messgeCount = messgeCount;
AppApplication.getInstance().setSport();
String unreadMessage = json.optString("unreadMessage");
if (!TextUtils.isEmpty(unreadMessage) && !"null".equals(unreadMessage)) {
List list = GsonUtil.stringToList(unreadMessage, MessgeEntity.class);
for (int i = 0; i < list.size() && i < 2; i++) {
String taskMessageType = list.get(i).getTaskMessageType();
if (TextUtils.isEmpty(taskMessageType)) {
showNotifictionIcon(getApplication(), list.get(i), "com.haocang.messge.ui2.MessgeTabLayouFragment", false, null, null);
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onErrorResponse(Response errorCode) {
}
};
public void showNotifictionIcon(Context context, MessgeEntity entity, String fragmentName, boolean toTaskPage, String type, String taskName) {
Class clazz = null;
try {
clazz = Class.forName("com.haocang.base.ui.CommonActivity");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (clazz != null) {
Intent intent = new Intent(getApplication(), clazz);//点击之后进入MainActivity
intent.putExtra("fragmentName", fragmentName);
intent.putExtra("messageId", entity.getId());
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, (int) entity.getId(), intent, PendingIntent.FLAG_UPDATE_CURRENT);//第二个参数如果id相同会覆盖之前的所有intent
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
String id = "channel_2";//删了会报错 。。。。。
String id_normal= "channel_1";
String name = "aaa";
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification notification;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String channel_id_actural=id_normal;
if (entity.getMessageCategory() == 2) {
channel_id_actural=id;
}else {
channel_id_actural=id_normal;
}
NotificationChannel mChannel = new NotificationChannel(channel_id_actural, name, NotificationManager.IMPORTANCE_LOW);
if(entity.getMessageCategory() == 2){
mChannel.setSound(sound, Notification.AUDIO_ATTRIBUTES_DEFAULT);
}
notificationManager.createNotificationChannel(mChannel);
notification = new Notification.Builder(this)
.setChannelId(channel_id_actural)
.setContentTitle(entity.getTitle())
.setContentText(entity.getContent())
.setContentIntent(pendingIntent)
.setSmallIcon(R.mipmap.ic_mango).build();
} else {
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setContentTitle(entity.getTitle())
.setContentText(entity.getContent())
.setSmallIcon(R.mipmap.ic_mango)
.setContentIntent(pendingIntent)
// .setDefaults(Notification.DEFAULT_SOUND)
.setOngoing(false);
// .setChannel(id);//无效
if (entity.getMessageCategory() == 2) {
notificationBuilder.setSound(sound, 5);
} else {
notificationBuilder.setDefaults(Notification.DEFAULT_SOUND);
}
notification = notificationBuilder.build();
}
notificationManager.notify((int) entity.getId(), notification);
}
}
}