Android学习之服务
完整测试代码,上Github<传送门>
快速查阅
STEP1: 创建好自己的Service文件
,并让它继承Service
,然后加上onBind
函数
public class ServiceTest extends Service {
...
/*onBlind这个方法其实就是用于和Activity建立关联的*/
@Override
public IBinder onBind(Intent intent) {
return null;
}
...
}
STEP2: 在主活动启动后台服务
通常在onStart
函数中进行!
/** 当活动即将可见时调用 */
@Override
protected void onStart()
{
Intent startIntent = new Intent(getApplicationContext(), ServiceTest.class);
startService(startIntent); //启动后台服务
...
super.onStart();
}
STEP3:在注册文件中注册服务
<service android:name=".ServiceMqtt" >
</service>
详细解读
1、自己建的服务,先继承Service
,然后加上onBind
。onBind
这个函数是创建一个Service
必须要有的。
public class MyService extends Service {
...
/*onBlind这个方法其实就是用于和Activity建立关联的*/
@Override
public IBinder onBind(Intent intent) {
return null;
}
...
}
2、还有记得在总的注册文件中(AndroidManifest.xml
)进行注册Service
,如果和主活动在一个包下,可以直接.×××
,譬如 下面的.MyService
<service android:name=".MyService" >
</service>
3、Stop Service
按钮只会让Service
停止,点击Unbind Service
按钮只会让Service
和Activity
解除关联,一个Service
必须要在既没有和任何Activity关联又处于停止状态的时候才会被销毁。
4、Thread
是用于开启一个子线程,在这里去执行一些耗时操作就不会阻塞主线程的运行。
每一个进程有好多线程,而必有一个主线程。
Service
是运行在主线程里的,也就是说如果你在Service
里编写了非常耗时的代码,程序必定会出现ANR的。
正确食用方法,在Service建立线程,进行耗时的操作。
/*标准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);
}
7、想要让Activity与Service之间建立关联,需要调用bindService()方法,并将Intent作为参数传递进去,在Intent里指定好要绑定的Service
Intent bindIntent = new Intent(this, MyService.class);
bindService(bindIntent, connection, BIND_AUTO_CREATE);
6、关于Service郭神两段精妙的话!
Android的后台就是指,它的运行是完全不依赖UI的。即使Activity被销毁,或者程序被关闭,只要进程还在,Service就可以继续运行。比如说一些应用程序,始终需要与服务器之间始终保持着心跳连接,就可以使用Service来实现。
你可能又会问,前面不是刚刚验证过Service是运行在主线程里的么?在这里一直执行着心跳连接,难道就不会阻塞主线程的运行吗?当然会,但是我们可以在Service中再创建一个子线程,然后在这里去处理耗时逻辑就没问题了。
既然在Service里也要创建一个子线程,那为什么不直接在Activity里创建呢?这是因为Activity很难对Thread进行控制,当Activity被销毁之后,就没有任何其它的办法可以再重新获取到之前创建的子线程的实例。而且在一个Activity中创建的子线程,另一个Activity无法对其进行操作。但是Service就不同了,所有的Activity都可以与Service进行关联,然后可以很方便地操作其中的方法,即使Activity被销毁了,之后只要重新与Service建立关联,就又能够获取到原有的Service中Binder的实例。因此,使用Service来处理后台任务,Activity就可以放心地finish,完全不需要担心无法对后台任务进行控制的情况。
8、防止Service被回收才使用前台Service,有些项目由于特殊的需求会要求必须使用前台Service,比如说墨迹天气,它的Service在后台更新天气数据的同时,还会在系统状态栏一直显示当前天气的信息
/*前台Service的写法*/
@Override
public void onCreate() {
super.onCreate();
showNotification(getApplicationContext());//文本通知
//showNotificationProgress(getApplicationContext());//带进度条的通知
Log.e(TAG, "onCreate() executed");
}
通知的具体实现,可参考这里。
贴上自己的两段实验程序:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private Button startService;
private Button stopService;
private Button bindService;
private Button unbindService;
private MyService.MyBinder myBinder;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myBinder = (MyService.MyBinder) service;//向下转型,实现在Activity中根据具体的场景来调用MyBinder中的任何public方法
myBinder.startDownload();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService = (Button) findViewById(R.id.start_service);
stopService = (Button) findViewById(R.id.stop_service);
bindService = (Button) findViewById(R.id.bind_service);
unbindService = (Button) findViewById(R.id.unbind_service);
startService.setOnClickListener(startServiceListener);
stopService.setOnClickListener(stopServiceListener);
bindService.setOnClickListener(bindServiceListener);
unbindService.setOnClickListener(unbindServiceListener);
Log.e("MyService", "MainActivity thread id is " + Thread.currentThread().getId());//打印线程id
}
private View.OnClickListener startServiceListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent startIntent = new Intent(MainActivity.this, MyService.class);
startService(startIntent);//onCreate()和onStartCommand()方法都会执行。
}
};
private View.OnClickListener stopServiceListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.e(TAG, "click stop");
Intent stopIntent = new Intent(MainActivity.this, MyService.class);
stopService(stopIntent);
}
};
private View.OnClickListener bindServiceListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent bindIntent = new Intent(MainActivity.this, MyService.class);
bindService(bindIntent, connection, BIND_AUTO_CREATE);//onCreate()方法得到执行,但onStartCommand()方法不会执行。
}
};
private View.OnClickListener unbindServiceListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.e(TAG, "click unbind" );
unbindService(connection);
}
};
}
MyService.java
public class MyService extends Service {
private static final String TAG = "MyService";
private MyBinder mBinder = new MyBinder();
@Override
public IBinder onBind(Intent intent) {
return null;
}
// @Override
// public void onCreate() {
//
// Log.e("MyService", "MyService thread id is " + Thread.currentThread().getId());//打印线程id
//
// super.onCreate();
// Log.e(TAG, "onCreate() executed");
// }
/*前台Service的写法*/
@Override
public void onCreate() {
super.onCreate();
//showNotification(getApplicationContext());//文本通知
//showNotificationProgress(getApplicationContext());//带进度条的通知
Log.e(TAG, "onCreate() executed");
}
/*标准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);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e(TAG, "onDestroy() executed");
}
class MyBinder extends Binder {
public void startDownload() {
new Thread(new Runnable() {
@Override
public void run() {
Log.e("TAG", "startDownload() executed");
// 执行具体的下载任务
}
}).start();
}
}
/**
* 显示一个普通的通知
*
* @param context 上下文
*/
public static void showNotification(Context context) {
Notification notification = new NotificationCompat.Builder(context)
/**设置通知左边的大图标**/
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher))
/**设置通知右边的小图标**/
.setSmallIcon(R.mipmap.ic_launcher)
/**通知首次出现在通知栏,带上升动画效果的**/
.setTicker("通知来了")
/**设置通知的标题**/
.setContentTitle("这是一个通知的标题")
/**设置通知的内容**/
.setContentText("这是一个通知的内容这是一个通知的内容")
/**通知产生的时间,会在通知信息里显示**/
.setWhen(System.currentTimeMillis())
/**设置该通知优先级**/
.setPriority(Notification.PRIORITY_DEFAULT)
/**设置这个标志当用户单击面板就可以让通知将自动取消**/
.setAutoCancel(true)
/**设置他为一个正在进行的通知。他们通常是用来表示一个后台任务,用户积极参与(如播放音乐)或以某种方式正在等待,因此占用设备(如一个文件下载,同步操作,主动网络连接)**/
.setOngoing(false)
/**向通知添加声音、闪灯和振动效果的最简单、最一致的方式是使用当前的用户默认设置,使用defaults属性,可以组合:**/
.setDefaults(Notification.DEFAULT_VIBRATE | Notification.DEFAULT_SOUND)
.setContentIntent(PendingIntent.getActivity(context, 1, new Intent(context, MainActivity.class), PendingIntent.FLAG_CANCEL_CURRENT))
.build();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
/**发起通知**/
notificationManager.notify(0, notification);
}
/**
* 显示一个下载带进度条的通知
*
* @param context 上下文
*/
public static void showNotificationProgress(Context context) {
//进度条通知
final NotificationCompat.Builder builderProgress = new NotificationCompat.Builder(context);
builderProgress.setContentTitle("下载中");
builderProgress.setSmallIcon(R.mipmap.ic_launcher);
builderProgress.setTicker("进度条通知");
builderProgress.setProgress(100, 0, false);
final Notification notification = builderProgress.build();
final NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
//发送一个通知
notificationManager.notify(2, notification);
/**创建一个计时器,模拟下载进度**/
Timer timer = new Timer();
timer.schedule(new TimerTask() {
int progress = 0;
@Override
public void run() {
Log.i("progress", progress + "");
while (progress <= 100) {
progress++;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//更新进度条
builderProgress.setProgress(100, progress, false);
//再次通知
notificationManager.notify(2, builderProgress.build());
}
//计时器退出
this.cancel();
//进度条退出
notificationManager.cancel(2);
return;//结束方法
}
}, 0);
}
}
学习郭神的文章总结:
https://blog.csdn.net/guolin_blog/article/details/11952435(上)
https://blog.csdn.net/guolin_blog/article/details/9797169(下)
<下>还没看,主要是应用在应用程序之间,用到再来研究!
文章来源: recclay.blog.csdn.net,作者:ReCclay,版权归原作者所有,如需转载,请联系作者。
原文链接:recclay.blog.csdn.net/article/details/81542561
- 点赞
- 收藏
- 关注作者
评论(0)