[置顶] Android四大核心组件之Service|AIDL使用详解

时间:2022-12-21 11:36:47

开头白:

什么是服务?

service可以说是一个在后台运行的Activity,它不是一个单独的进程,它只需要应用告诉它要在后台做什么就可以了。

它要实现和用户的交互的话需要通过通知栏或则是发送广播,UI去接收显示。它的应用十分广泛,尤其是在框架层,应用更多的是对系统服务的调用。

服务有什么用

它用于处理一些不干扰用户使用的后台操作。如下载,网络获取。播放音乐,他可以通过INTENT来开启,同时也可以绑定到宿主对象(调用者例如ACTIVITY上)来使用。

Service的简介
1.Service介绍和作用
Service是Android系统中的四大组件之一,它是一种长生命周期的,没有可视化界面,运行于后台的一种服务程序。比如我们播放音乐的时候,有可能想边听音乐边干些其他事情,当退出播放音乐的应用,如果不用Service,我 们就听不到歌了,所以这时候就得用到Service了。
[置顶]        Android四大核心组件之Service|AIDL使用详解
Service生命周期
Service的生命周期并不像Activity那么复杂,它只继承了onCreate(),onStart(),onDestroy()三个方法,当第一次启动Service时,先后调用了onCreate(),onStart()这两个方法,当停止Service时,则执行onDestroy()方法,这里需要注意的是,如果Service已经启动了,当我们再次启动Service时,不会在执行onCreate()方法,而是直接执行onStart()方法。

Service的启动方式
Service的有两种启动方式:Context.startService()和Context.bindService(),这两种方式对Service生命周期的影响是不同的。


代码实现:

1.你要写一个类继承service重写onStartCommand()方法, 并在该方法中实现服务的核心业务

public class MyService extends Service {

//在改方法中实现服务的核心业务
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "服务已开启", 1000).show();
return super.onStartCommand(intent, flags, startId);
}

}

2.注意使用一个服务你需要在AndroidManifest.xml文件中进行注册:
enabled:是否开启这一服务
exported:这个服务是否外界可用

<service android:name=".MyService"
android:enabled="true"
android:exported="true">

</service>

3.最后在MainActivity 中使用一个intent启动一个服务:
*你可以使用StopSlef()方法来自己停止自己!

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

public void button1(View v) {
Intent intent=new Intent(this,MyService.class);
startService(intent);
}
}

service线程内容小点:
(1)一个服务是在主线程内执行的,如果服务内执行耗时的操作时会影响主线程的堵塞。从而影响用户体验。
(2)解决方案:使用一个新的线程来完成服务中的耗时操作


onStartComand的返回值

onStartComand使用时,返回的是一个(int)整形。
这个整形可以有四个返回值:

//start_sticky
//start_no_sticky
//START_REDELIVER_INTENT
//START_STICKY_COMPATIBILITY
它们的含义分别是:
1):START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
2):START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务
3):START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
4):START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。

IntentService

IntentService 是继承于 Service 并处理异步请求的一个类,在 IntentService 内有一个工作线程来处理耗时操作,启动 IntentService 的方式和启动传统 Service 一样,同时,当任务执行完后,IntentService 会自动停止,而不需要我们去手动控制。另外,可以启动 IntentService 多次,而每一个耗时操作会以工作队列的方式在IntentService 的 onHandleIntent 回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推。

而且,所有请求都在一个单线程中,不会阻塞应用程序的主线程(UI Thread),同一时间只处理一个请求。 那么,用 IntentService 有什么好处呢?首先,我们省去了在 Service 中手动开线程的麻烦,第二,当操作完成时,我们不用手动停止 Service。

代码实现:

1.你要写一个类继承Intentservice重写onStartCommand()方法, 并在该方法中实现服务的核心业务

注意最后不要忘了在配置文件中注册你的Intentservice服务哦!!!

public class MyIntentServie extends IntentService {

//在改方法中实现服务的核心业务
@Override
protected void onHandleIntent(Intent intent) {
// TODO Auto-generated method stub

Toast.makeText(getApplicationContext(), "服务已开启", 1000).show();
}

}

IntentService小结:
(1)实现IntentService我们需要继承自Intentservice
(2)重写onStartCommand()方法
(3)IntentService 是继承于 Service 并处理异步请求的一个类
(4)在 IntentService 内有一个工作线程来处理耗时操作
(5)启动 IntentService 的方式和启动传统 Service 一样


Android AIDL使用详解

1.先提一下IPC,他的全名叫做:跨进程通信(interprocess communication),
因为在Android系统中,个个应用程序都运行在自己的进程中,进程之间一般是无法直接进行数据交换的,
而为了实现跨进程,Android给我们提供了上面说的Binder机制,而这个机制使用的接口语言就是:
AIDL(Android Interface Definition Language),他的语法很简单,而这种接口语言并非真正的编程
语言,只是定义两个进程间的通信接口而已!而生成符合通信协议的Java代码则是由Android SDK的
platform-tools目录下的aidl.exe工具生成,生成对应的接口文件在:gen目录下,一般是:Xxx.java的接口!
而在该接口中包含一个Stub的内部类,该类中实现了在该类中实现了IBinder接口与自定义的通信接口,
这个类将会作为远程Service的回调类——实现了IBinder接口,所以可作为Service的onBind( )方法的返回值!
Android AIDL使用详解传送门http://blog.csdn.net/stonecao/article/details/6425019


Adnroid studio生成的 Icat.java文件是在:

[置顶]        Android四大核心组件之Service|AIDL使用详解

eclipse生成的 Icat.java文件是在:
[置顶]        Android四大核心组件之Service|AIDL使用详解


[置顶]        Android四大核心组件之Service|AIDL使用详解
AIDL使用详解有点麻烦
但是android为我我们提供了方便的Messenger

详细源码:

MainActivity.java

package com.example.messengersevices;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.view.View;

public class MainActivity extends Activity {

boolean isBound=false;//判断是否绑定成功的一个标记

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}


//点击按钮时启动服务
public void button1(View v) {
Intent intent=new Intent(this,mySerivce.class);

/*注意我们使用bindService方法绑定服务
* 参数(一个Intent,绑定服务连接的会掉接口,一个标记);
* 参数标记:我们通常写 Context.BIND_AUTO_CREATE表示:如果自动开启一个服务在绑定
*/

bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
//绑定服务连接成功时回掉接口
private ServiceConnection conn=new ServiceConnection() {

//服务异常时回调的方法
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub

isBound=false;
}
//绑定成功后回调的方法
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub

isBound=true;

Messenger messenger;
messenger=new Messenger(service);

//获取一个消息对象
Message message=Message.obtain();
//通过消息对象设置消息内容
message.what=100;

try {
messenger.send(message);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
};

//点击按钮时解绑服务
public void button2(View v) {
//如果返回isBound的值是true我们就可以解绑
if(isBound) {
unbindService(conn);
}
}
}

mySerivce.java

package com.example.messengersevices;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Messenger;
import android.widget.Toast;

public class mySerivce extends Service {
//第三步
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return messenger.getBinder();
}
//第二步
Handler handler=new Handler(){
public void handleMessage(android.os.Message msg) {

switch (msg.what) {
case 100:
Toast.makeText(getApplicationContext(), "绑定成功", 1000).show();
break;

}
};
};
//第一步
Messenger messenger=new Messenger(handler);
}

activity_main.xml

 <Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/button1"
android:layout_below="@+id/button1"
android:layout_marginTop="142dp"
android:text="解绑服务"
android:onClick="button2" />

<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="58dp"
android:text="启动服务"
android:onClick="button1" />

最后不要忘了在配置文件中注册服务:

 <service android:name=".mySerivce"
android:enabled="true"
android:exported="true">

</service>

完!