android service 优点,Android之Service

startService(): run indefinetly, 需要在适当时候stopSelf()

onBind(): 提供一个CS模式的服务,runs as long as the component bound to it. 当所有组件都unBind() 时,Service也就destroy了。

Service运行于主进程,因此勿做耗时工作,如果需要,可以开启新的线程来做耗时的work,以避免ANR。

声明周期lifecycle

onStartCommand()

当用户调用startService()请求启动服务,系统就会调用该方法。当该方法运行后,service就会在后台runs indefinitely.如果自己实现该方法,则需要自己调用stopSelf()或者stopService()来关闭服务。

onBind()

其他component调用bindService(),系统就会调用该方法。如不想被bind,则返回null,否则返回一个IBinder()。

onCreate()

当Service第一次被调用时,系统将调用该方法进行初始化,然后才会调用onStartCommand或者onBind. 如果该Service已经启动则跳过该步骤。

onDestory()

清理资源,诸如线程,注册的listeners,receivers等。

Caution: always use an explicit intent when starting or binding your Service

可将android:exported属性设为false, 这样就可以组织其他应用,即使是使用explicit intent也无法启动Service。

Traditionally,有两种Create Service的方式:

Service, 如有Intensive work,需要手动创建线程进行处理,否则容易造成ANR, as it is hosted in main thread

IntentService, Service的子类,使用worker thread 依次处理所有请求,需要继承onHandleIntent(),然后处理从onStartCommand收到的intent。

Extending the IntentService class

优点:

create 默认的worker thread, 处理所有来自onStartCommand收到的Intent请求。

Create a work queue, 依次传递收到intent到onHandleIntent(),依次处理。

在处理完所有请求后,就会自动销毁Service,无需自己调用stopSelf()

提供默认的onBind()实现,返回null。

提供一个默认的onStartCommand实现,它会将intent发送到work queue,并依次传递到onHandleIntent()

实例:

All you need: a constructor and an implementation of onHandleIntent().

public class HelloIntentService extends IntentService {

/**

* A constructor is required, and must call the super IntentService(String)

* constructor with a name for the worker thread.

* 一个构造函数,且需调用super,并传入该service名

*/

public HelloIntentService() {

super("HelloIntentService");

}

/**

* The IntentService calls this method from the default worker thread with

* the intent that started the service. When this method returns, IntentService

* stops the service, as appropriate.

*/

@Override

protected void onHandleIntent(Intent intent) {

// Normally we would do some work here, like download a file.

// For our sample, we just sleep for 5 seconds.

long endTime = System.currentTimeMillis() + 5*1000;

while (System.currentTimeMillis() < endTime) {

synchronized (this) {

try {

wait(endTime - System.currentTimeMillis());

} catch (Exception e) {

}

}

}

}

}

注意,如果override 其他的方法,则必须调用super,让其帮助管理声明周期。比如对于onStartCommand()

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();

return super.onStartCommand(intent,flags,startId);

}

Extending the Service class

如果需要同步处理多个请求,而不是按照队列依次处理,则继承Service,然后再对每个请求启动一个thread进行处理。

实例代码(有许多需要说明)

public class HelloService extends Service {

private Looper mServiceLooper;

private ServiceHandler mServiceHandler;

// Handler that receives messages from the thread

private final class ServiceHandler extends Handler {

public ServiceHandler(Looper looper) {

super(looper);

}

@Override

public void handleMessage(Message msg) {

// Normally we would do some work here, like download a file.

// For our sample, we just sleep for 5 seconds.

long endTime = System.currentTimeMillis() + 5*1000;

while (System.currentTimeMillis() < endTime) {

synchronized (this) {

try {

wait(endTime - System.currentTimeMillis());

} catch (Exception e) {

}

}

}

// Stop the service using the startId, so that we don't stop

// the service in the middle of handling another job

stopSelf(msg.arg1);

}

}

@Override

public void onCreate() {

// Start up the thread running the service. Note that we create a

// separate thread because the service normally runs in the process's

// main thread, which we don't want to block. We also make it

// background priority so CPU-intensive work will not disrupt our UI.

HandlerThread thread = new HandlerThread("ServiceStartArguments",

Process.THREAD_PRIORITY_BACKGROUND);

thread.start();

// Get the HandlerThread's Looper and use it for our Handler

mServiceLooper = thread.getLooper();

mServiceHandler = new ServiceHandler(mServiceLooper);

}

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();

// For each start request, send a message to start a job and deliver the

// start ID so we know which request we're stopping when we finish the job

Message msg = mServiceHandler.obtainMessage();

msg.arg1 = startId;

mServiceHandler.sendMessage(msg);

// If we get killed, after returning from here, restart

return START_STICKY;

}

@Override

public IBinder onBind(Intent intent) {

// We don't provide binding, so return null

return null;

}

@Override

public void onDestroy() {

Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();

}

}

第一点,新建HandleThread,与普通Thread无异,但是多了一个Looper成员。

第二点,正常来讲,Service是可以使用handler的,因为它是主线程,默认已经具有了Looper。但是官方demo还是根据新建的HandlerThread的成员looper,传入了Handler。

第三点,对于onStartCommand返回值START_STICKY,总共可以返回三个值,定义了在系统杀掉服务后系统如何继续服务。

START_NOT_STICKY

当系统杀掉Service后,不进行recreate.

START_STICKY

当系统杀掉Service后,recreate and call onStartCommand(), 不传递last intent.适合于media play, 不执行commands,只是runs indefinitely.

START_REDELIVER_INTENT

当系统杀掉Service后,recreate and call onStartCommand(), 携带last intent. 适合于正在执行任务的需要被立刻被恢复的,如下载。

Application Component 与Service交互,除了startService,无其他活动。若想得到Service的返回结果,可用PendingIntent 携带一个getBroadcast()对象,这样在Service使用完成后,即可发送发送广播。

Creating a Bound Service

可通过调用bindService()

To Create a Bound Service,必须实现onBind()返回一个IBinder对象,该对象定义了与Service通信的接口。

当Client不再需要Service,需要调用unbindService() 进行解绑,使得服务科正常关闭。

Sending Notifications to the User

使用Toast 或者状态栏notification。

状态栏Notification时best practise, 可在service结束后,发送通知,然后用户可点击通知栏的通知,然后启动一个Activity。

Running a Service in the Foreground

A foreground service必须提供一个notification for the status bar, 将被放置在正在运行的条目下,不可移除,除非Service运行完毕或者被移除前台。

实例:

Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),

System.currentTimeMillis());

Intent notificationIntent = new Intent(this, ExampleActivity.class);

PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

notification.setLatestEventInfo(this, getText(R.string.notification_title),

getText(R.string.notification_message), pendingIntent);

startForeground(ONGOING_NOTIFICATION_ID, notification);

现在Notification已经使用Notification.Build进行建立了。

可使用stopForeground(),但不会停止Service。但是stopService()可以移除notification。

Managing the Lifecycle of a Service

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值