Android开发之Service

什么是Service?

Android中的服务与Activity不同,他是不能与用户进行交互,自己也不能启动在后台运行的程序,当我们退出应用时,Service应用并没有结束,它仍然在后台运行。

例子:

我们播放音乐,此时又要去干别的事的时候。如果没有Services退出播放音乐的应用我们就听不到歌。

如何获取启动Service实例?

可以使用bindService()实现。

初步了解Services的用法:

代码:

 1 package com.example.hxdn.servicetest;
 2 
 3 import android.content.Intent;
 4 import android.support.v7.app.AppCompatActivity;
 5 import android.os.Bundle;
 6 import android.util.Log;
 7 import android.view.Menu;
 8 import android.view.MenuItem;
 9 import android.view.View;
10 import android.widget.Button;
11 
12 public class MainActivity extends AppCompatActivity {
13 
14     private  static final String BiaoQian="MainActivity";
15     private Button btn1=null;
16     private Button btn2=null;
17     @Override
18     protected void onCreate(Bundle savedInstanceState) {
19         super.onCreate(savedInstanceState);
20         setContentView(R.layout.activity_main);
21         Log.i(BiaoQian,"onCreate() executed");
22         btn1=(Button)findViewById(R.id.btn1);
23         btn2=(Button)findViewById(R.id.btn2);
24         btn1.setOnClickListener(new View.OnClickListener() {
25             @Override
26             public void onClick(View v) {
27                 Intent startIntent=new Intent(MainActivity.this,MyService.class);
28                 startService(startIntent);
29             }
30         });
31         btn2.setOnClickListener(new View.OnClickListener() {
32             @Override
33             public void onClick(View v) {
34                 Intent stopIntent=new Intent(MainActivity.this,MyService.class);
35                 stopService(stopIntent);
36             }
37         });
38 
39     }
40 
41     @Override
42     public boolean onCreateOptionsMenu(Menu menu) {
43         // Inflate the menu; this adds items to the action bar if it is present.
44         getMenuInflater().inflate(R.menu.menu_main, menu);
45         return true;
46     }
47 
48     @Override
49     public boolean onOptionsItemSelected(MenuItem item) {
50         // Handle action bar item clicks here. The action bar will
51         // automatically handle clicks on the Home/Up button, so long
52         // as you specify a parent activity in AndroidManifest.xml.
53         int id = item.getItemId();
54 
55         //noinspection SimplifiableIfStatement
56         if (id == R.id.action_settings) {
57             return true;
58         }
59 
60         return super.onOptionsItemSelected(item);
61     }
62 }
package com.example.hxdn.servicetest;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

/**
 * Created by hxdn on 2015/9/16.
 */
public class MyService extends Service {
    public final static  String TAG="MyService";
    @Override
    public void  onCreate()
    {
        super.onCreate();
        Log.i(TAG,"onCreate() executed");
    }
    @Override
    public  int onStartCommand(Intent intent,int flags,int startId)
    {
        Log.i(TAG, "onCommand() executed");
        return super.onStartCommand(intent, flags, startId);

    }
    @Override
    public  void  onDestroy()
    {
        super.onDestroy();
        Log.i(TAG, "onDestroy() executed");
    }
    @Override
   public IBinder onBind(Intent intent)
    {
        return null;
    }
}
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 3     package="com.example.hxdn.servicetest">
 4 
 5     <application
 6         android:allowBackup="true"
 7         android:icon="@mipmap/ic_launcher"
 8         android:label="@string/app_name"
 9         android:theme="@style/AppTheme">
10         <activity
11             android:name=".MainActivity"
12             android:label="@string/app_name">
13             <intent-filter>
14                 <action android:name="android.intent.action.MAIN" />
15 
16                 <category android:name="android.intent.category.LAUNCHER" />
17             </intent-filter>
18         </activity>
19         <service android:name="com.example.hxdn.servicetest.MyService"></service>
20     </application>
21 
22 </manifest>

布局代码只是写两个按钮启动和关闭Setvice。

注意点:

1、Services与Activity同为四大组件都需要注册!

2、如果Services已经创建过(onCreate()),且没有被销毁,接下来再启动Services(startService())只会执行(onStartCommand())。

Service和Activity通信

先贴上代码:

MainActivity:

 1 package com.example.hxdn.servicetest;
 2 
 3 import android.content.ComponentName;
 4 import android.content.Intent;
 5 import android.content.ServiceConnection;
 6 import android.os.IBinder;
 7 import android.support.v7.app.AppCompatActivity;
 8 import android.os.Bundle;
 9 import android.util.Log;
10 import android.view.Menu;
11 import android.view.MenuItem;
12 import android.view.View;
13 import android.widget.Button;
14 
15 public class MainActivity extends AppCompatActivity {
16 
17     private  static final String BiaoQian="MyService";
18     private Button btn1=null;
19     private Button btn2=null;
20     private Button btn3=null;
21     private Button btn4=null;
22     private MyService.MyBinder mybinder=null;
23     private ServiceConnection serviceConnection=new ServiceConnection() {
24         @Override
25         public void onServiceConnected(ComponentName name, IBinder service) {
26             Log.i(BiaoQian,"onServiceConnected() executed");
27             mybinder=(MyService.MyBinder)service;
28             mybinder.startDownLoad();
29         }
30 
31         @Override
32         public void onServiceDisconnected(ComponentName name) {
33             Log.i(BiaoQian,"onServiceDisconnected() executed");
34         }
35     };
36     @Override
37     protected void onCreate(Bundle savedInstanceState) {
38         super.onCreate(savedInstanceState);
39         setContentView(R.layout.activity_main);
40         Log.i(BiaoQian, "onCreate() executed");
41         btn1=(Button)findViewById(R.id.btn1);
42         btn2=(Button)findViewById(R.id.btn2);
43         btn3=(Button)findViewById(R.id.btn3);
44         btn4=(Button)findViewById(R.id.btn4);
45         btn1.setOnClickListener(new View.OnClickListener() {
46             @Override
47             public void onClick(View v) {
48                 Intent startIntent=new Intent(MainActivity.this,MyService.class);
49                 startService(startIntent);
50             }
51         });
52         btn2.setOnClickListener(new View.OnClickListener() {
53             @Override
54             public void onClick(View v) {
55                 Log.i(BiaoQian, "click Stop Service button");
56                 Intent stopIntent=new Intent(MainActivity.this,MyService.class);
57                 stopService(stopIntent);
58             }
59         });
60         btn3.setOnClickListener(new View.OnClickListener() {
61             @Override
62             public void onClick(View v) {
63                 Intent bindIntent=new Intent(MainActivity.this,MyService.class);
64                 bindService(bindIntent,serviceConnection,BIND_AUTO_CREATE);
65             }
66         });
67         btn4.setOnClickListener(new View.OnClickListener() {
68             @Override
69             public void onClick(View v) {
70                 Log.i(BiaoQian, "click Unbind Service button");
71                unbindService(serviceConnection);
72             }
73         });
74 
75     }
76 
77     @Override
78     public boolean onCreateOptionsMenu(Menu menu) {
79         // Inflate the menu; this adds items to the action bar if it is present.
80         getMenuInflater().inflate(R.menu.menu_main, menu);
81         return true;
82     }
83 
84     @Override
85     public boolean onOptionsItemSelected(MenuItem item) {
86         // Handle action bar item clicks here. The action bar will
87         // automatically handle clicks on the Home/Up button, so long
88         // as you specify a parent activity in AndroidManifest.xml.
89         int id = item.getItemId();
90 
91         //noinspection SimplifiableIfStatement
92         if (id == R.id.action_settings) {
93             return true;
94         }
95 
96         return super.onOptionsItemSelected(item);
97     }
98 }

MyService:

 1 package com.example.hxdn.servicetest;
 2 
 3 import android.app.Service;
 4 import android.content.Intent;
 5 import android.os.Binder;
 6 import android.os.IBinder;
 7 import android.util.Log;
 8 
 9 /**
10  * Created by hxdn on 2015/9/16.
11  */
12 public class MyService extends Service {
13     public final static  String TAG="MyService";
14     private MyBinder myBinder=new MyBinder();
15     @Override
16     public void  onCreate()
17     {
18         super.onCreate();
19         Log.i(TAG,"onCreate() executed");
20     }
21     @Override
22     public  int onStartCommand(Intent intent,int flags,int startId)
23     {
24         Log.i(TAG, "onCommand() executed");
25         return super.onStartCommand(intent, flags, startId);
26 
27     }
28     @Override
29     public  void  onDestroy()
30     {
31         super.onDestroy();
32         Log.i(TAG, "onDestroy() executed");
33     }
34     @Override
35     public void  onRebind(Intent intent)
36     {
37         super.onRebind(intent);
38         Log.i(TAG,"onRebind() executed");
39     }
40     @Override
41     public  boolean  onUnbind(Intent intent)
42     {
43         Log.i(TAG,"onUnbind()");
44         return super.onUnbind(intent);
45 
46     }
47     @Override
48    public IBinder onBind(Intent intent)//返回类型为IBinder,其主要作用是Service与外界交互的一种手段,
49                                         // 而IBinder对象数据类型是接口。
50     {
51         return myBinder;
52     }
53     class MyBinder extends Binder
54     {
55         public void startDownLoad()
56         {
57             Log.i(TAG,"startDownLoad() executed");
58         }
59     }
60 }

这里我们新增了一个MyBinder类继承自Binder类,然后在MyBinder中添加了一个startDownload()方法用于在后台执行下载任务,当然这里并不是真正地去下载某个东西,只是做个测试,所以startDownload()方法只是打印了一行日志。

我所理解的Activity与Services通信的机制是:

1、首先Service里需要有一个Binder的类,类似构建起临时的契约。而且需要复写onBind(Intent intent),并返回一个Binder对象。

2、在Activity里需要获得连接,所学需要ServiceConnection的匿名类,在里面重写了onServiceConnected(ComponentName name, IBinder service)

方法和onServiceDisconnected()方法,这两个方法分别会在Activity与Service建立关联和解除关联的时候调用。参数service便是MyService里的onBinder()方法返回的。

便可通过这个这个实例调用Binder类里的方法,我们便可以在Activity中根据具体的场景来调用MyBinder中的任何public方法,即实现了Activity指挥Service干什么Service就去干什么的功能。

3、Activity与Service需要进行绑定

Intent bindIntent=new Intent(MainActivity.this,MyService.class);
bindService(bindIntent,serviceConnection,BIND_AUTO_CREATE);
BIND_AUTO_CREATE:表示绑定后自动创建Service实例。

解绑:
unbindService(serviceConnection);

注意点:
如果我们既点击了Start Service按钮,又点击了Bind Service按钮会怎么样呢?这个时候你会发现,不管你是单独点击Stop Service按钮还是Unbind Service按钮,Service都不会被销毁,必要将两个按钮都点击一下,Service才会被销毁。也就是说,点击Stop Service按钮只会让Service停止,点击Unbind Service按钮只会让Service和Activity解除关联,一个Service必须要在既没有和任何Activity关联又处理停止状态的时候才会被销毁。

Service和Thread的关系

service是后台进程并且运行在主线程,Thread是子线程。

两者没有任何关系。

Android的后台就是指,它的运行是完全不依赖UI的。即使Activity被销毁,或者程序被关闭,只要进程还在,Service就可以继续运行。

面对后台的耗时操作,我们可以在Service写一个子线程。

那为什么不直接在Activity里创建呢?这是因为Activity很难对Thread进行控制,当Activity被销毁之后,就没有任何其它的办法可以再重新获取到之前创建的子线程的实例。而且在一个Activity中创建的子线程,另一个Activity无法对其进行操作。但是Service就不同了,所有的Activity都可以与Service进行关联,然后可以很方便地操作其中的方法,即使Activity被销毁了,之后只要重新与Service建立关联,就又能够获取到原有的Service中Binder的实例。因此,使用Service来处理后台任务,Activity就可以放心地finish,完全不需要担心无法对后台任务进行控制的情况。

一个较为标准的Service:

 1 @Override
 2 public int onStartCommand(Intent intent, int flags, int startId) {
 3     new Thread(new Runnable() {
 4         @Override
 5         public void run() {
 6             // 开始执行后台任务
 7         }
 8     }).start();
 9     return super.onStartCommand(intent, flags, startId);
10 }
11 
12 class MyBinder extends Binder {
13 
14     public void startDownload() {
15         new Thread(new Runnable() {
16             @Override
17             public void run() {
18                 // 执行具体的下载任务
19             }
20         }).start();
21     }
22 
23 }

修改by:http://blog.csdn.net/guolin_blog/article/details/11952435

 

你可能感兴趣的:(Android开发之Service)