Android学习-服务的基本用法

来源:互联网 发布:超图软件工资怎么样 编辑:程序博客网 时间:2024/06/06 17:50

服务是android实现程序后台运行的解决方案,适合去执行那些不需要和用户交互,而需要长期运行的任务。服务的运行不依赖于任何用户的界面,服务并不是在一个独立的进程中,而是依赖创建服务时所在的应用程序进程,当应用程序进程被杀掉,服务终止。
服务不会自动开启线程,所有的代码都是默认在主线程中进行的。我们需要在服务的内部手动创建子线程,并在这里执行具体的任务,否则有可能出现主线程被阻塞的情况

一.定义一个服务

直接在项目的com.example.*包中直接右击新建New→Service。有两个属性需要选择
Exported:是否允许其他程序访问这个服务。
Enabled:表示是否启用这个服务。
服务是继承了service类的,一般要重写以下方法;
onCreate()
在服务创建的时候被调用,一般先于onStartCommand
onStartCommand()
每次服务启动的时候调用
onDestory()
在服务销毁的时候绑定
onBind()
常用于活动与服务的绑定等。。。

其他方法:
stopService()和stopSelf():停止服务
服务的生命周期:
1.在项目的任何位置调用Context的startService()方法,相应的服务就会启动,并回调onStartCommand()方法,如果这个服务之前没有创建过,则需要先调用onCreate.没调用一次startService(), onStartCommand()就会被调用一次,实际上每个服务只会存在一个实例。最后只需要调用一次stopService()或stopSelf()就可以停止服务。
2.Context的binService()用来获取一个服务的持久连接,这时就会回调服务中的onBind()方法,类似的,如果没创建过要先onCreate();之后方可调用onBind()方法里面返回的Ibinder对象的实例,就能自由的和服务进行通信了。
3.调用startService()方法之后,又调用stopService()方法,这时候服务中的onDestory()方法就会被执行;当调用bindService()之后,调用unbindSevice(),onDestory()方法也会被执行;、
注意当对一个服务即调用startService又调用bindService,要同时调用stopService和unBindService,onDestory()方法才会被执行;

二.服务的使用

活动与服务之间通信的实例:
xml文件

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"   android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent">    <Button        android:id="@+id/start_service"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="Start Service"    />    <Button        android:id="@+id/stop_service"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="Stop Service"/>    <Button        android:id="@+id/bind_service"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="Bind Service"        />    <Button        android:id="@+id/unbind_service"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="Unbind Service"/>    <Button        android:id="@+id/start_intent_service"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="Start IntentService"/></LinearLayout>

MyService服务类:

public class MyService extends Service {    public 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 IBinder onBind(Intent intent){            return mBinder;        }    }    @Override    public IBinder onBind(Intent intent) {        // TODO: Return the communication channel to the service.        //throw new UnsupportedOperationException("Not yet implemented");        return mBinder;    }    @Override    public void onCreate() {        super.onCreate();        Log.d("MyService","onCreate executed");        Intent intent=new Intent(this,MainActivity.class);        PendingIntent pi=PendingIntent.getActivity(this,0,intent,0);        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);    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.d("MyService","onStartCommand executed");        return super.onStartCommand(intent, flags, startId);    }    @Override    public void onDestroy() {        super.onDestroy();        Log.d("MyService","onDestroy executed");    }}

DownloadBinder类继承自Binder,然后在里面提供了两个模拟的方法,接着在MyService中创建了DownloadBinder的实例,然后在onBind()方法里返回这个实例。

MainActivity类

public class MainActivity extends AppCompatActivity implements View.OnClickListener {    private  MyService.DownloadBinder downloadBinder;    private ServiceConnection connection=new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            downloadBinder=(MyService.DownloadBinder) service;            downloadBinder.startDownload();            downloadBinder.getProgress();        }        @Override        public void onServiceDisconnected(ComponentName componentName) {        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Button startService=(Button) findViewById(R.id.start_service);        Button stopService=(Button) findViewById(R.id.stop_service);        startService.setOnClickListener(this);        stopService.setOnClickListener(this);        Button bindService=(Button) findViewById(R.id.bind_service);        Button unbindService=(Button) findViewById(R.id.unbind_service);        bindService.setOnClickListener(this);        unbindService.setOnClickListener(this);        Button startIntentService =(Button) findViewById(R.id.start_intent_service);        startIntentService.setOnClickListener(this);    }    @Override    public void onClick(View v) {        switch (v.getId()){            case R.id.start_service:                Intent startIntent = new Intent(this,MyService.class);                startService(startIntent);                break;            case R.id.stop_service:                Intent stopIntent=new Intent(this,MyService.class);                stopService(stopIntent);                break;            case R.id.bind_service:                Intent bindIntent=new Intent(this,MyService.class);                bindService(bindIntent,connection,BIND_AUTO_CREATE);//绑定服务                break;            case R.id.unbind_service:                unbindService(connection);//解绑服务                break;            case R.id.start_intent_service:                Log.d("MainActivity","Thread id is"+Thread.currentThread().getId());                Intent intentService =new Intent(this,MyIntentService.class);                startService(intentService);                break;            default:                break;        }    }}

创建了一个ServiceConnection匿名类,在里面重写了onServiceConnected()和onServiceDisconnected()方法,分别在活动与服务成功绑定与断开的时候调用。在onServiceConnected()中,向下转型的得到了DownloadBinder的实例。可以在活动中,通过这个实例来指挥服务区干什么工作。

活动与服务要进行绑定与解绑:首先构建出一个Intent对象,然后调用bindService()方法将MainActivity和MyService进行绑定。bindService方法接收三个参数,第一个是构建的Intent对象,第二个是前面创建的ServiceConnection实例,第三个是标志位,这里传入BIND_AUTO_CREATE表示活动和服务在进行绑定之后自动创建服务,这会让Myservice中的onCreate方法执行,但是onStartCommand方法不会执行。
与bindService()对应的是unbindService()解绑,使用如上。

IntentService类

public class MyIntentService extends IntentService {    public MyIntentService() {        super("MyIntentService");//调用父类的有参构造函数    }    protected  void onHandleIntent(Intent intent){        //打印当前线程的is        Log.d("MyIntentService","Thread id is"+Thread.currentThread().getId());    }    @Override    public void onDestroy() {        super.onDestroy();        Log.d("MyIntentService","onDestory executed");    }}

一般为了防止忘记调用stopSelf(),Android提供了一个异步的,会自动终止服务的IntentService类。onHandleIntent()是在子线程中运行的,可以去处理一些具体的逻辑。

3.服务的多线程

注意:服务的代码默认实在主线程中运行,如果直接在服务里去处理一些逻辑,一般容易出现ANR(Application Not Responding).这个时候就要用到多线程技术。应该为服务的每个具体的方法开启一个子线程去处理耗时的逻辑,标准的写法如下:

public class Myservice extends Service(){    ...    @Override    public int OnstartCommand(Intent intent,int flags,int startId){        new Thread(new Runnable(){            public void run(){                //处理具体的逻辑            }        }).start();    }}