android基础之Service
一:Service的概述
Service是Android四大基本组件(Service,Activity,Context Provider,BroadcastReceiver它们之间依靠Intent建立联系)中与Activity最相似的组件。都代表 执 行的程序,Service与Activity的区别在于:
Service一直在后台运行,它没有用户界面,所以绝不会到前台 来。一旦Service被启动起来之后,它就与Activity一样。完全具有自己的生命周期。
关于程序中Activity和service的选择标准:
如果某个程序组件需要在运行时向用户呈现某种界面,或者该程序需要与用户交互,就需要使用Activity,否则就应该考虑使用Service了。
如:下载东西,播放音乐。可以一边下载,一边播放,一边玩其他的事情。但是Activity是无法做到的。只要Activity被关闭或者最小化了,程序就停止了。
二:特点
1.没有UI
2.进行耗时较长或者与用户没有交互的一些功能
3.Service具有较高的优先级,比stop的Activity优先级要高,最高的优先级是前台Activity
4.具有较长的生命周期
三.使用
看到这里你也许会问为什么Service会有2中生命周期呢。哈哈,
其实这是跟Service的使用方式有关的。Service有2中不同的使用方式。
我们先创建一个android application project工程,然后在默认包下新建一个class,取名为firstService 继承Service如图:
既然Service是我们自定义的,当然我们要在清单文件里面注册一下。(在AndroidManifest.xml的 <application>标签加入如下内容):
name里面放的是类的包名+类名,一般会有提示。
第一种使用方式(对应最左边的图)
这里我在主界面放了个按钮,然后设置的android:onClick="btn2"
这种方式启动的Service,并没有将之与Activity绑定,所以作为一个单独存在的实体,本身的生命周期不受别人影响。也没有办法与其他组件之间进行数据交互。
就像我们电脑的一些一些系统服务一样,很多时候我们是通过强制手段关闭的。
第二种方式,对应最右边的图。
通常情况下,我们希望一个后台的Service是可控的,同时用户也希望知道这个服务的运行状态,就拿下载东西来说,有的时候用户希望看到实时的数据变化。第一种方式在这种情况下显然不能满足我们的需求,毕竟大多数场景下,用户希望服务受自己掌控,同时灵活的数据是app的灵魂。
我们知道,service没有ui所以要通过Activity提供ui。第二种方式就是通过activity与service的绑定实现的。用同样的方式,我们在布局里面再放一个按钮,然后设置的android:onClick="btn1"在activity的主函数里面定义按钮点击事件。
前面都差不多。就启动时用
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
启动。原理都说的差不多了。建议写代码时对着生命周期来写。
package com.example.mydemo;
import com.example.mydemo.secondService.mybinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity {
private mybinder mybinder;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
//当访问者与之连接成功时调用
@Override
public void onServiceConnected(ComponentName name, IBinder ibinder) {
// TODO Auto-generated method stub
mybinder = (com.example.mydemo.secondService.mybinder) ibinder;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* startService所启动的服务
* 1.它是不受任何人影响的
* 2.它是作为一个单独的个体存在的,没有办法与其他组件之间进行数据交互
* @param view
*/
public void btn(View view){
Toast.makeText(MainActivity.this, mybinder.getCount()+"", Toast.LENGTH_LONG).show();
}
public void btn1(View view){
unbindService(serviceConnection);
}
public void btn2(View view){
Intent intent = new Intent(this,secondService.class);
// startService(intent);
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
}
/**
* 如果使用bindServiuce启动的服务,那么service就与调用者的生命周期就有关联了,
* 所以退出时也要终止service
*/
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
unbindService(serviceConnection);
super.onDestroy();
}
}
创建2个service自己随便取名字,别忘了在清单文件注册就是。
第一个service对应第一种启动方式:
package com.example.mydemo;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class firstService extends Service {
final String tag = "firstService";
boolean flag = true;//逻辑控制开关
int count=0;//测试参数
@Override
public void onCreate() {
// TODO Auto-generated method stub
Log.i(tag, tag+"....onCreate()");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Log.i(tag, tag+"....onStartCommand()");
new Thread(){
public void run() {
while(flag){
System.out.println("进度:"+count++);
if(count>99){
flag=false;
}
try {
sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();;
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
Log.i(tag, tag+"....onDestroy()");
flag = false;
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
第一个service对应第二种启动方式:
package com.example.mydemo;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class secondService extends Service{
boolean flag = true;
final String tag = "secondService";
int count=0;
class mybinder extends Binder{
public int getCount(){
return count;
}
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
Log.i(tag, tag+"....onCreate()");
super.onCreate();
}
//建立契约
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Log.i(tag, tag+"....onBind()");
new Thread(){
public void run() {
while(flag){
System.out.println("进度:"+count++);
if(count>100){
flag=false;
}
try {
sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
return new mybinder();
}
//解除契约
@Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
Log.i(tag, tag+"....onUnbind()");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
flag = false;
Log.i(tag, tag+"....onDestroy()");
super.onDestroy();
}
}
activity的主函数调用
package com.example.mydemo;
import com.example.mydemo.secondService.mybinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity {
private mybinder mybinder;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
//当访问者与之连接成功时调用
@Override
public void onServiceConnected(ComponentName name, IBinder ibinder) {
// TODO Auto-generated method stub
mybinder = (com.example.mydemo.secondService.mybinder) ibinder;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* startService所启动的服务
* 1.它是不受任何人影响的
* 2.它是作为一个单独的个体存在的,没有办法与其他组件之间进行数据交互
* @param view
*/
public void btn(View view){
Toast.makeText(MainActivity.this, mybinder.getCount()+"", Toast.LENGTH_LONG).show();
}
public void btn1(View view){
unbindService(serviceConnection);
}
public void btn2(View view){
Intent intent = new Intent(this,secondService.class);
// startService(intent);
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
}
/**
* 如果使用bindServiuce启动的服务,那么service就与调用者的生命周期就有关联了,
* 所以退出时也要终止service
*/
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
unbindService(serviceConnection);
super.onDestroy();
}
}
效果就不发了。反正第二种方式所打开的service它的生命周期已经和activity绑定了。
这种方式可以让我们自定义地暂停和重启服务。