0
点赞
收藏
分享

微信扫一扫

android开发 - Service服务


android开发 - Service服务_启动服务



Service没有UI,因为service是后台运行


如:下载,网络I/O 等等


Service的生命周期
    从它被创建开始,到它被销毁为止,


    onCreate();
    onStartCommand();
    onBind();
    onUnbind();
    onRebind();
    onDestroy();
    
一般分为三种方式


第一种:
    当采用Context.startService()方法启动服务,与之有关


的生命周期方法
    onCreate() -> onStartCommand() -> onDestroy()
    
    onCreate()该方法在服务被创建时调用,该方法只会被调


用一次,无论调用多少次startService()或bindService()方


法,服务也只被创建一次
    onStart() 只有采用Context.startService()方法启动服


务时才会调用该方法,该方法在服务开始运行时被调用,多次


调用startService()方法尽管不会多次创建服务,但onStart


()方法会被多次调用
    onDestroy()该方法在服务被终止时调用


第二种:
    当采用Context.bindService()方法启动服务,与之有关


的生命周期方法
    onCreate() -> onBind() -> onUnbind() -> onDestroy


()
    onBind() 只有采用Context.bindService()方法启动服务


时才会回调该方法,该方法在调用者与服务绑定时被盗用,当


调用者与服务已经绑定,多次调用,Context.bindService()方


法并不会导致该方法被多次调用。
    onUnbind()只有采用Context.bindService()方法启动服


务时才会回调该方法,该方法在调用者与服务解除绑定时被调


用。


第三种:混合启动绑定服务
   如果先采用startService()方法启动服务,然后调用


bindService方法绑定到服务,在调用unbindService()方法


解除绑定,最后调用bindService()方法再次绑定到服务,触


发的生命周I方法如下:

onCreate() -> 
   onStartCommand() -> 
   onBind() ->  onUnbind()[重载后的方法需返回true]    


 -> 
   onRebind()       






 采用Service实现电话窃听器


 1.新建一个类继承Service
   /*
  * 采用Service实现电话窃听器
  */
 public class PersonService extends Service {


// 该方法只会被调用一次
@Override
public void onCreate() {
super.onCreate();
// 取得电话管理服务
TelephonyManager telephonyManager = 


 (TelephonyManager) getSystemService


 (Context.TELEPHONY_SERVICE);
telephonyManager.listen(new 


 PhoneListener(),



 PhoneStateListener.LISTEN_CALL_STATE);


}


// 电话监听器
private final class PhoneListener extends 


 PhoneStateListener {
private String incomingNumberString;
private MediaRecorder mediaRecorder;
private File file;


@Override
public void onCallStateChanged(int 


 state, String incomingNumber) {
switch (state) {
// 来电
case 


 TelephonyManager.CALL_STATE_RINGING:



 this.incomingNumberString = incomingNumber;


break;
// 接通电话
case 


 TelephonyManager.CALL_STATE_OFFHOOK:
try {
file = new 


 File(Environment.getExternalStorageDirectory(),



 incomingNumber + System.currentTimeMillis());
mediaRecorder 


 = new MediaRecorder();



 mediaRecorder.setAudioSource


 (MediaRecorder.AudioSource.MIC);
mediaRecorder



 .setOutputFormat


 (MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder



 .setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);



 mediaRecorder.setOutputFile(file.getAbsolutePath());



 mediaRecorder.prepare();// 准备



 mediaRecorder.start();// 开始录音
} catch (IOException 


 e) {
}
break;
// 挂断电话回归到空闲状态
case 


 TelephonyManager.CALL_STATE_IDLE:
if (mediaRecorder != 


 null) {



 mediaRecorder.stop();



 mediaRecorder.release();
mediaRecorder 


 = null;
}
break;
}
}
}


@Override
public IBinder onBind(Intent intent) { 
return null;
} 
 }      


 2.配置清单文件
   <service android:name=".MyService" />


 3.服务是不能自己运行的是需要调用启动服务
   比如说,开机启动,那么需要使用广播接收者,
   然后从广播启动服务


   开机启动的广播接收者配置
   <receiver 


 android:name="com.example.service_demo.broadcast.MyBro


 adcast">
      <intent-filter>
           <action 


 android:name="android.intent.action.BOOT_COMPLETED"  


 />
      </intent-filter>
   <receiver>


   代码:
   public class MyBroadcast extends BroadcastReceiver {


@Override
public void onReceive(Context context, Intent 


 intent) {
context.startService(new Intent


 (context,MyService.class)); 
}
 }






 4.配置必要的权限
       <!-- 电话状态读取权限 -->
     <uses-permission 


 android:name="android.permission.READ_PHONE_STATE" />
     <!-- SDCARD写权限 -->
     <uses-permission 


 android:name="android.permission.WRITE_EXTERNAL_STORAG


 E" />
     <!-- SDCARD中创建和删除文件权限 -->
     <uses-permission 


 android:name="android.permission.MOUNT_UNMOUNT_FILESYS


 TEMS" /> 
     <!-- 网络权限 -->
     <uses-permission 


 android:name="android.permission.INTERNET" />
     <!-- 刻录声音的权限 -->
     <uses-permission 


 android:name="android.permission.RECORD_AUDIO" />




5.现在就可以启动了
  然后打电话就会被录音


  现在服务是在系统中启动了,但是怎么停止了?
  如果不显示关闭服务,而是由系统自己来关闭,就是当内存 


 不够时,先终结掉后台继承,如果后台进程还不够,那么就  


 需要结束掉服务进程
  
  手动调用关闭服务是
   Context.stopService(); 


















建立能与访问者进行相互通信的本地服务


通过startService()和stopService()启动关闭服务,适用于


服务和访问者之间没有交互的情况


如果服务和访问者之间需要方法调用或者传递参数,则需要使


用bindService()和unbindServie()方法启动关闭服务


采用Context.bindService()方法启动服务,在服务未被创建


时,系统会先调用服务的onCreate()方法,接着调用onBind()


方法,这个时候访问者和服务绑定在一起,如果访问者要与服


务进行通信,那么,onBind()方法必须返回IBinder对象,


如果访问者退出了,系统就会先调用服务器的onUnbind(),接


着调用onDestroy()方法,如果调用bindService()方法前服务


已经被绑定多次调用bindService()方法并不会导致多次创


建服务及绑定(也就是说onCreate()和onBind()方法并不会被


多次调用),


如果访问者希望与正在绑定的服务解除绑定,可以调用


unbindService()方法,调用该方法也会导致调用系统的


unbind()   ->   onDestroy()






访问者调用服务中的方法


1.当我们启动调用bindService()时,系统会调用Service类的


onBind()方法 ,返回IBinder对象,所以我们创建一个内部类


继承自Binder,并且声明一个全局IBinder对象,返回Binder对


象的实例


2.创建一个继承service的类

/*
  * 绑定服务的过程是:客户启动服务,服务返回一个IBinder


 对象
  * 由于IBinder是一个接口,所以我们需要自定一个类继承


 Binder对象,然后把这个类的实例对象给接口对象
  * 在将这个接口对象给返回
  */
 public class MyService extends Service {


private String[] nameStrings = {"小明","小


 王","夏利","校长"};

private IBinder binder = new StudentBinder();

public String query(int id){
if(id > 0 && id < 4){
return nameStrings[id-1];
}
return null;
}

@Override
public IBinder onBind(Intent intent) { 
return binder;
}

private class StudentBinder extends Binder 


 implements IStudent{
public String queryStudent(int id){
return query(id);
}
} 
 }


 3.创建一个接口
   public interface IStudent {
String queryStudent(int id);
 }


 4.在Activity中调用
   
 public class MainActivity extends Activity {


private ServiceConnection conn= new 


 StudentServiceConnection();
private IStudent iStudent;

     @Override
     protected void onCreate(Bundle savedInstanceState) 


 {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         
         final TextView tv = (TextView)


 this.findViewById(R.id.textview);
         final EditText txt = (EditText)


 this.findViewById(R.id.editText);
         this.findViewById


 (R.id.button).setOnClickListener(new 


 View.OnClickListener() {
@Override
public void onClick(View v) { 
String text = 


 iStudent.queryStudent(Integer.valueOf(txt.getText


 ().toString()));
tv.setText(text);
}
});
         
         
         
         
         Intent service = new Intent


 (this,MyService.class);
         bindService(service, conn, BIND_AUTO_CREATE);
     } 
     
     private class StudentServiceConnection implements 


 ServiceConnection{
@Override
public void onServiceConnected


 (ComponentName name, IBinder service) {
iStudent = (IStudent)service;
} 
 
@Override
public void onServiceDisconnected


 (ComponentName name) {
iStudent = null;
} 
     }
     
     @Override
     protected void onDestroy() {
     //当activity被摧毁时注销绑定
     unbindService(conn);
     super.onDestroy();
     }
 }






 这种服务就类似QQ中的发送一条消息,需要经过这样的服务过


 程
 当然,发送UDP信息,没有写,这里只是讲绑定服务需要执行


 的过程





使用AIDL和远程服务实现进程通信


AIDL就是进程间通信


Android Interface Definition Language


AIDL是一种接口定义语言,用于约束两个进程间的通讯规则,
供编译器生成代码








1.新建一个项目 作为服务端
  新建一个接口,并且把这个.java文件格式改成.aidl
  并且不能有访问修饰符
  刷新项目,在gen下会生成一个文件,不过这里的文件不需


要我们来改,系统自动生成的


2.现在创建一个服务
  代码

public class queryStudentService extends Service {
private IBinder binder = new 


 StudentQueryBinder();
private String[] str = {"小王","呵呵","哈哈"};
public String query(int id){
return str[id];
}

@Override
public IBinder onBind(Intent intent) {
 
return binder;
}

private final class StudentQueryBinder extends 


 StudentQuery.Stub{


@Override
public String queryStudent(int number) 


 throws RemoteException {
return query(number);
} 
} 
     }
     
     配置文件
     <service 


 android:name="com.example.android_remote_aidl.service.


 queryStudentServic">
             <intent-filter><action 


 android:name="com.enenya.service.queryStudentService"/


 ></intent-filter>
         </service>



  
3.写一个客户端
  把服务端的那个aidl包复制到客户端项目中来

public class MainActivity extends Activity {


     private ServiceConnection conn = new 


 StudentServiceConnection();
private StudentQuery studentQuery;
     
     @Override
     protected void onCreate(Bundle savedInstanceState) 


 {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
     
         
         final TextView tv = (TextView)


 this.findViewById(R.id.textview);
         final EditText editText = (EditText) 


 this.findViewById(R.id.edittext);
         this.findViewById


 (R.id.button).setOnClickListener(new 


 View.OnClickListener(){
@Override
public void onClick(View v) {
try {
String aString 


 = studentQuery.queryStudent(Integer.valueOf


 (editText.getText().toString()));
tv.setText


 (aString);
} catch 


 (NumberFormatException e) {
// TODO Auto-


 generated catch block



 e.printStackTrace();
} catch 


 (RemoteException e) {
// TODO Auto-


 generated catch block



 e.printStackTrace();
}


}
         });
         
         
         Intent service = new Intent


 ("com.enenya.service.queryStudentService");
         bindService(service, conn, BIND_AUTO_CREATE);
     }


     private class StudentServiceConnection implements 


 ServiceConnection{


@Override
public void onServiceConnected


 (ComponentName name, IBinder service) {
studentQuery = 


 StudentQuery.Stub.asInterface(service);
}


@Override
public void onServiceDisconnected


 (ComponentName name) {
studentQuery = null;
}
     }
     
     @Override
     protected void onDestroy() {
     unbindService(conn);
     super.onDestroy();
     }
     
     
 }




举报

相关推荐

0 条评论