Android Service 详解四:开始停止service

开始一个Service

  你可以从一个activity或从其它应用的组件通过传递一个Intent(指定了要启动的服务)startService()启动一个服务.Android系统然后调用serviceonStartCommand()方法并且把Intent传递给它.(你永远不能直接调用onStartCommand())


  例如,一个activity可以在调用startService()时使用一个明确的intent开始前文的例子中的service(HelloSevice)

Intentintent = new Intent(this, HelloService.class);

startService(intent);


  startService()方法会立即返回然后Android系统调用serviceonStartCommand()方法.但是如果service尚没有运行,系统会先调用onCreate(),然后调用onStartCommand().


  如果service没有提供绑定功能,传给startService()intent是应用组件与service之间唯一的通讯方式.然而,如果你希望service回发一个结果,那么启动这个service的客户端可以创建一个用于广播(使用getBroadcast())PendingIntent然后放在intent中传给serviceservice然后就可以使用广播来回送结果.


  不同的启动请求导致对serviceonStartCommand()的不同调用,但停止service的请求只有一个(使用stopSelf()stopService())


停止一个service

  一个"启动的"service必须管理其自己的生命期.这表示,系统不会停止或销毁这种service,除非内存不够用了并且serviceonStartCommand()返回后会继续运行.所以,service必须调用stopSelf()停止自己或由另一个组件调用stopService()来停止它.


  一旦通过stopSelf()stopService()发出了停止请求,系统就会尽可能快地销毁service


  然而,如果你的service同时处理多个对onStartCommand()的请求,那么你不应在处理完一个请求之后就停止service,因为你可能已经又收到了新的启动请求(在第个完成后停止将会结束掉第二个).要避免这个问题,你可以使用stopSelf(int)来保证你的停止请求对应于你最近的开始请求.也就是,当你调用stopSelf(int)时,你传递开始请求的ID(传递给onStartCommand()startId)service,如果service在你调用stopSelf(int)之前收到一了个新的开始请求,发现ID不同,于是service将不会停止.


  注意:你的应用在完成工作后停止它所有的service是非常重要的.这可以避免浪费系统资源和消耗电量.如果需要,其它的组件可以调用stopService()停止service.即使你为service启用了绑定,你也必须自己停止service,甚至它收到了对onStartCommand()的调用也这样.


创建一个绑定的Service

  一个绑定的service是允许应用的组件通过调用bindService()来绑定它以创建一个能长期存在的连接(并且一般不允许组件调用startService()来启动它)


  当你的activity或其它组件想与service交互或你的应用想基于IPC的向其它应用提供功能时,你应该创建一个绑定的service


  要创建一个绑定的service,你必须实现回调方法onBind(),还要在其中返回一个IBinder,这个IBinder定义了与service通讯的接口.其它应用组件就可以在之后调用bindService()来接收这个接口并开始调用service的方法.service只在有应用组件绑定到它时才活着,所以当没有组件绑定到它时,系统就会宰了它(你不需去停止一个绑定的service,跟用onStartCommand()启动的service不一样)


  要创建一个绑定的service,首先要做的就是定义客户端如何与service通讯的接口.这个接口必须是IBinder的一个实现,并且必须被回调方法onBind()返回.一旦客户端接收到IBinder,它就可以开始与service进行交互.


  多个客户端可以一起绑定到一个service.当一个客户端完成与service的交互,它调用unbindService()来解除绑定.一旦不再有任何客户端绑定到service,系统就宰了这个service


  有很多方法来实现一个绑定的service并且这些实现要比"开始的"service难懂得多.


发送通知给用户

  一旦开始运行,一个service可以通过Toast通知或状态栏通来通知用户一些事件.


  一个toast通知是一个出现在当前窗口表面上并过一会就消失的消息.当一个状态栏通知提供一个带有消息的图标到状态栏,用就可以先定它来执行一些动作(比如启动一个activity)


  通常,一个状态栏通知是当一些后台工作(比如一个文件下载完成了)完成后通知用户可以对它进行动作的最佳方式.当用户选择这个通知时,它可以开始一个activity(比如可以查看下载的文件)



发布了0 篇原创文章 · 获赞 1 · 访问量 1万+
展开阅读全文

android 启动service出现问题,直接“很抱歉,已停止运行”

05-02

在activity的onResume()方法启动服务,直接“很抱歉,已停止运行” protected void onResume() { super.onResume(); if(isNetworkAvailable()) { Log.e("login_resume", "+++++++++++++++++++++++"); Intent service = new Intent(this, GetMsgService.class); startService(service); }else { toast(this); } 我的service是下面的内容,主要是通过一个client启动读写线程,用于socket的传输: import com.example.client.Client; import com.example.client.ClientInputThread; import com.example.client.MessageListener; import com.example.tran.bean.TranObject; import com.example.util.Constants; import com.example.util.SharedPreferencesUtil; import android.app.Application; import android.app.Service; import android.content.Context; import android.content.Intent; import android.os.IBinder; import android.util.Log; public class GetMsgService extends Service{ private MyApplication myApplication; private SharedPreferencesUtil util; private Client client; private Context context = this; private boolean isStart = false;// 是否与服务器连接上 @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); myApplication = (MyApplication) this.getApplicationContext(); client = myApplication.getClient(); Log.e("service_oncreate", "++++++++++++++++++++"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub super.onStartCommand(intent, flags, startId); isStart = client.start(); myApplication.setClientStart(isStart); System.out.print(isStart); Log.e("service", "+++++++++++++++++++++++++++++"); if(isStart) { ClientInputThread inputThread = client.getClientInputThread(); inputThread.setMessageListener(new MessageListener() { @Override public void Message(TranObject tranObject) { // TODO Auto-generated method stub Intent broadcast = new Intent(); broadcast.setAction(Constants.ACTION); broadcast.putExtra(Constants.MSGKEY, tranObject); sendBroadcast(broadcast); } }); } return START_REDELIVER_INTENT; } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } } 问答

安卓,service,不调用ondestory()方法,并强退,怎么办?

11-25

代码如下,本应按下第二个按钮就调用service的ondestory方法,但没有,并且会强退。 activity_main.xml: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" android:orientation="vertical"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="打开service"/> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="销毁service"/> </LinearLayout> java代码如下: package com.example.test_service; import android.os.Bundle; import android.widget.*; import android.app.Activity; import android.view.Menu; import android.app.Service; import android.os.IBinder; import android.content.Intent; import android.view.View.OnClickListener; import android.view.View; public class MainActivity extends Activity { Button but=null; Button but2=null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); but=(Button)super.findViewById(R.id.button); but2=(Button)super.findViewById(R.id.button2); but.setOnClickListener(new OnClickListenerimpl()); but2.setOnClickListener(new OnClickListenerimpl2()); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } class OnClickListenerimpl implements OnClickListener { public void onClick(View v) { startService(new Intent(MainActivity.this,Test.class)); } } class OnClickListenerimpl2 implements OnClickListener { public void onClick(View v) { stopService(new Intent(MainActivity.this,Test.class)); } } } 另外该service的类如下: package com.example.test_service; import android.app.Service; import android.content.Intent; import android.os.IBinder; public class Test extends Service { public IBinder onBind(Intent intent) { return null; } public void onCreate() { System.out.println("现在create了service"); } public int onStartCommand(Intent intent,int flag,int startId) { System.out.println("现在启动service,启动的id是"+startId); return Service.START_CONTINUATION_MASK; } public void onDestory() { System.out.println("现在销毁service"); } } 另外,在AndroidMainfest.xml中已添加如下语句: <service android:name=".Test"/> 按下“打开service”按钮,logcat如下图: ![图片说明](https://img-ask.csdn.net/upload/201511/25/1448434665_954634.png) 按下“销毁service",后台并不会输出相应的信息,而是等一段时间后就会如图: ![图片说明](https://img-ask.csdn.net/upload/201511/25/1448434712_930375.png) 此时也会弹出提示框要强退: ![图片说明](https://img-ask.csdn.net/upload/201511/25/1448434738_234231.png) 请问是什么问题?应该怎么解决? 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览