https://github.com/YuQiao0303/ServiceTest-LearnAndroid
新建服务
com.example.servicetest→New→Service→Service
Exported 属性表示是否允许除了当前程序之外的其他程序访问这个服务
Enabled 属性表示是否启用这个服务。
服务
- 创建,启动,销毁时分别调用onCreate(), onStartCommant(), on Destroy()
- onBind()中return一个自定义的binder对象,里面可以写很多方法,供绑定的activity调用
package com.example.servicetest;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {
private static final String TAG = "MyService";
private DownloadBinder mBinder = new DownloadBinder();
class DownloadBinder extends Binder {
public void startDownload() {
Log.d("MyService", "startDownload executed");
}
public int getProgress() {
Log.d("MyService", "getProgress executed");
return 0;
}
}
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return mBinder;
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate: ");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand: ");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy: ");
super.onDestroy();
}
}
启动/停止服务
会执行onCreate(),onStartCommant(),onDestroy() 等方法
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent); // 启动服务
//stopService(stopIntent); // 停止服务
在MyService的任何一个位置调用stopSelf()
方法也能让这个服务停止下来。
绑定/解绑服务
可以调用onBind()返回的自定义binder的方法
Intent bindIntent = new Intent(this, MyService.class);
//BIND_AUTO_CREATE 表示在活动和服务进行绑定后自动创建服务。
//这会使得MyService中的onCreate() 方法得到执行, 但onStartCommand() 方法不会执行。
bindService(bindIntent, connection, BIND_AUTO_CREATE); // 绑定服务,执行onBind。如果之前没创建则还要执行onCreate
//unbindService(connection); // 解绑服务 ,调用onDestroy()
如果既启动又绑定,则要同时调用stopService() 和unbindService() 方法, onDestroy() 方法才会执行。
使用前台服务:在状态栏显示
- 不会由于系统内存不足的原因导致被回收
- 一直有一个正在运行的图标在系统的状态栏显示, 下拉状态栏后可以看到更加详细的信息, 非常类似于通知的效果。
在service中:
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate: ");
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pi;
pi = PendingIntent.getActivity(this, 0, intent, 0);
/**
* 8.0及以上:前台服务
*/
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
/*create notification channel*/
String channelId = "1";
String channelName = "1";
int importance = NotificationManager.IMPORTANCE_HIGH;
createNotificationChannel(channelId, channelName, importance);
/*show the notification*/
Notification notification = new NotificationCompat.Builder(this, channelId)
.setContentTitle("This is content title")
.setContentText("This is content text")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(),
R.mipmap.ic_launcher))
.setContentIntent(pi)
.build();
startForeground(1, notification);//调用startForeground() 方法后就会让MyService变成一个前台服务, 并在系统状态栏显示出来。
}
/**
* 7.0及以下:前台服务
*/
else{
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle("This is content title")
.setContentText("This is content text")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(),
R.mipmap.ic_launcher))
.setContentIntent(pi)
.build();
startForeground(1, notification);
}
}
版本兼容问题:
郭神自己的文章
服务里干什么?——运行线程!
服务中的代码都是默认运行在主线程当中的,
如果直接在服务里去处理一些耗时的逻辑, 就很容易出现ANR(Application Not Responding) 的情况。
所以这个时候就需要用到Android多线程编程的技术了, 我们应该在服务的每个具体的方法里开启一个子线程, 然后在这里去处理那些耗时的逻辑。
因此, 一个比较标准的服务就可以写成如下形式,即在onStartCommand中运行线程:
public class MyService extends Service {
...
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
// 处理具体的逻辑
}}).start();
return super.onStartCommand(intent, flags, startId);
}
}
如此一来,我们也可以使用
- AsyncTask(异步消息机制,可以改UI),
- IntentService :自动停止的服务,其onHandleIntent(Intent intent) 方法在子线程运行
使用IntentService :自动停止的线程
总会有一些程序员忘记开启线程, 或者忘记调用stopSelf() 方法。
Android专门提供了一个IntentService 类
可以简单地创建一个异步的、 会自动停止的服务
activity:
case R.id.start_intent_service:
// 打印主线程的id
Log.d("MainActivity", "Thread id is " + Thread.currentThread().
getId());
Intent intentService = new Intent(this, MyIntentService.class);
startService(intentService);
break;
MyIntentService:
package com.example.servicetest;
import android.app.IntentService;
import android.content.Intent;
import android.util.Log;
public class MyIntentService extends IntentService {
/**
* 首先要提供一个无参的构造函数
*/
public MyIntentService() {
super("MyIntentService"); // 调用父类的有参构造函数
}
/**
* 在子线程中运行
* @param intent
*/
@Override
protected void onHandleIntent(Intent intent) {
// 打印当前线程的id
Log.d("MyIntentService", "Thread id is " + Thread.currentThread(). getId());
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("MyIntentService", "onDestroy executed");
}
}
logcat: