(1).just(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10);
将传入的参数一次发送出来。
(2).from(iterable);
将传入的数组或者iterable拆分成具体的对象之后,一次发出来 。
(3).flatMap(func)
将解释它之前,先看一段代码
private void test(){
List<Student> list = new ArrayList<SiyActivity.Student>();
list.add(new Student("张三丰", new String[]{"a","b","c","d","e"}));
list.add(new Student("Tobby", new String[]{"1","2","3"}));
list.add(new Student("Corey", new String[]{"哈哈","嘿嘿","呲呲","默默","讷讷","enene"}));
Observable.from(list)
.flatMap(new Func1<Student, Observable<String>>() {
@Override
public Observable<String> call(Student arg0) {
// TODO Auto-generated method stub
return Observable.from(arg0.curors);
}
})
.subscribe(new Action1<String>() {
@Override
public void call(String arg0) {
Log.d("TAG", "cursors:"+arg0);
}
});
}
我们在通过from传入了一个学生的List,然后我们输出了每个学生所对应的课程,然而我们并没有使用for循环去遍历每
个学生的课程数组一个一个的输出,而是使用了flatMap使每一个学生的课程创建成了一个Observable然后交给Subsc
riber去处理。这就是flatMap的作用,不知道这样有没有很好的解释flatMap的用法。
(4).filter(predicate)
如果对于上面的代码,我们只想输出我们要求的课程名称(如a,b,1,3),这就会用到filter操作符了,filter()输出和输
入相同的元素,并且会过滤掉那些不满足检查条件的。
source.filter(new Func1<String, Boolean>() {
@Override
public Boolean call(String arg0) {
return arg0.matches("[a13b]");
}
});
(5).take(count)
上面的操作会输出4个结果,但是我现在只想输出满足我结果的3个名称,这样我就会使用take操作符,take(3)就行了
(6).doOnNext(onNext)
doOnNext()允许我们在每次输出一个元素之前做一些额外的事情。
(7).mergeWith(t1)
将两个或更多同类型的 Observable可以合并到一起去创建一个 Observable。
(8).zipWith(other, zipFunction)
将other与source进行合并返回,并且返回的个数由最小的那个指定
source .zipWith(Observable.range(10, 4), new Func2<String, Integer, String>() {
@Override
public String call(String arg0, Integer arg1) {
Log.d("TAG", "zipwith:"+arg1);
return arg0;
}
})
.zipWith(list, new Func2<String, Student, String>() {
@Override
public String call(String arg0, Student arg1) {
// TODO Auto-generated method stub
return arg0+arg1.name;
}
})
(9).repeatWhen(notificationHandler)
接收到.onCompleted()事件后触发Func1中的call方法,但是这样有什么用呢?关键是看Func1的输入参数和返回参
数,Func1<Observable<? extends Void>, Observable<?>>() 接收一个Observable <? extends void>返回有一个Ob
servable<?>,这样我们就能在事件发送完了之后重新再发送一次,这样我们就能简单的实现轮询数据。
source.repeatWhen(new Func1<Observable<? extends Void>, Observable<?>>() {
@Override
public Observable<?> call(Observable<? extends Void> arg0) {
Log.d("TAG", "repeatWhen");
return arg0.delay(5, TimeUnit.SECONDS);
}
})
每隔5秒轮询一次。
(10).retryWhen(notificationHandler)
接收到.onError()事件后触发Func1中的call方法,这个操作符其实同上面的操作符相似,只是触发的条件不一样,但
是我们看retryWhen的Func1<Observable<? extends Throwable>, Observable<?>>()的参数,接收的是一个Observa
ble<? extends Throwable>返回一个Observable<?>,这样又能干什么呢?看下面的一段代码:
source.retryWhen(new Func1<Observable<? extends Throwable>, Observable<?>>() {
@Override
public Observable<?> call(Observable<? extends Throwable> arg0) {
return arg0.zipWith(Observable.range(1, 3), new Func2<Throwable, Integer, Object>() {
@Override
public Object call(Throwable arg0, Integer arg1) {
Log.d("TAG", "exception:"+arg0);
if (arg0 instanceof IOException) {
return arg1;
}else{
return Observable.error(arg0);
}
}
}).flatMap(new Func1<Object, Observable<? extends Object>>() {
@Override
public Observable<? extends Object> call(Object arg0) {
if (arg0 instanceof Integer) {
return Observable.timer((long)Math.pow(2, (Integer)arg0), TimeUnit.SECONDS);
}else{
return Observable.error((Throwable)arg0);
}
}
});
}})
当发生IOException的时候,每隔2^
arg0秒重新发送一次事件,一共重新发送3次,如果不是IOException则直接onErr
or()。
第二部分:Android 跨进程通信
个人认为Android 的跨进程通信方式有5种,分别为:访问他应用的Activity、接收其他应用的广播、访问其它应用的
开放数据、AIDL和Messenger的跨进程通信。
(1)访问他应用的Activity
举一个简单的例子:
这个就是调用系统打电话的代码。这就是一个简单的Activity的跨进程通信。
private void test_1(){
Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:123654789"));
startActivity(callIntent);
}
那么Activity跨进程是怎么实现的呢?
服务端:(注:服务端和客户端是不同应用)
<activity
android:name="xyzefg.xxx.yyyy.cccc.ServiceActivity" >
<intent-filter>
<action android:name="com.service.activity" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="service" />
</intent-filter>
</activity>
public class ServiceActivity extends Activity{
TextView tv ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.service);
if (getIntent().getData() != null) {
String host = getIntent().getData().getHost();
Bundle bundle = getIntent().getExtras();
String value = bundle .getString("value");
tv = (TextView) findViewById(R.id.tv);
tv.setText(host+":"+value);
}
}
}
客户端:
private void test_2(){
Intent callIntent = new Intent("com.service.activity", Uri
.parse("service://跨进程请求Activity" ));
Bundle extras = new Bundle();
extras.putString("value", "我可是跨进程的");
callIntent.putExtras(extras);
startActivity(callIntent);
}
服务端主要实现分为三步:
1,设置启动的action <action/>
2,定义一个访问协议 <data/>
3,设置默认分类 <category/>
客户端:只要按照对应的action和协议就能请求到服务端的Activity
(2)接收其他应用的广播
举个简单的例子:
动态注册监听系统没分钟变化的广播。
private void registerTimeReceiver(){
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_TIME_CHANGED);
intentFilter.addAction(Intent.ACTION_TIME_TICK);
registerReceiver(myReceive, intentFilter);
}
BroadcastReceiver myReceive = new BroadcastReceiver(){
@Override
public void onReceive(Context arg0, Intent arg1) {
Log.d("TAG","触发了");
}
};
那么广播的跨进程是怎么实现的呢?
发送者:(注:发送者和接受者是不同的应用)
private void test_3(){
Intent intent = new Intent("com.my.receiver");
intent.putExtra("value", "我可是跨进程的");
sendBroadcast(intent);
}
接收者:
public class MyReceiver extends BroadcastReceiver{
public final static String ACTION = "com.my.receiver";
@Override
public void onReceive(Context arg0, Intent arg1) {
if (arg1.getAction() == ACTION) {
Log.d("TAG", arg1.getStringExtra("value"));
}
}
}
注册广播:
①动态注册:
private void registerTimeReceiver(){
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(MyReceiver.ACTION);
registerReceiver(myReceiver, intentFilter);
}
②
静态注册:
<receiver android:name="xyzefg.xxx.yyyy.cccc.MyReceiver" >
<intent-filter>
<action android:name="com.my.receiver" />
</intent-filter>
</receiver>
定义一个广播接收需要继承BroadcastReceiver 并从写里面的onReceiver 方法,并且不要忘记注册广播,并且指定广
播接收的Action。发送广播只需要定义一个意图对象的action指向接收的Receiver,然后调用sendBroadcast(Intent)。
(3)访问其它应用的开放数据
举一个简单的例子:
查询手机联系人。
private void test_4(){
ContentResolver contentResolver = getContentResolver();
Cursor cursor = contentResolver.query(android.provider.Contacts.Phones.CONTENT_URI, null, null, null, null);
while (cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex(android.provider.Contacts.Phones.NAME));
String num = cursor.getString(cursor.getColumnIndex(android.provider.Contacts.Phones.NUMBER));
Log.d("TAG", "name:"+name+"\nPhoneNum:"+num);
}
}
相比上面2个ContentProvider相对来说是麻烦多了。
服务端:(注:服务端和客户端不是同一个应用)
Andriod:
package com.example.hellojni;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
@DatabaseTable(tableName = "android")
public class Android {
@DatabaseField(columnName="_id",generatedId = true)
private Integer id;
@DatabaseField(columnName = "name")
private String name;
@DatabaseField(columnName = "version")
private String version;
public Android() {
}
public Android(String name,String version){
this.name = name;
this.version = version;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
}
DataBaseHelper:
package com.example.hellojni;
import java.sql.SQLException;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;
public class DataBaseHelper extends OrmLiteSqliteOpenHelper{
private final static String TABLENAME = "android";
private static DataBaseHelper instance;
private static Dao<Android, Integer> androidDao;
private DataBaseHelper(Context context) {
super(context, TABLENAME, null, 1);
}
public static synchronized DataBaseHelper getHelper(Context context)
{
if (instance == null)
{
synchronized (DataBaseHelper.class)
{
if (instance == null)
instance = new DataBaseHelper(context.getApplicationContext());
}
}
return instance;
}
@Override
public void onCreate(SQLiteDatabase arg0, ConnectionSource arg1) {
try {
TableUtils.createTable(arg1, Android.class);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void onUpgrade(SQLiteDatabase arg0, ConnectionSource arg1, int arg2, int arg3) {
try {
TableUtils.dropTable(arg1, Android.class, true);
onCreate(arg0, arg1);
} catch (SQLException e) {
e.printStackTrace();
}
}
public Dao<Android, Integer> getAndroidDao(){
if (androidDao == null) {
try {
androidDao = super.getDao(Android.class);
} catch (SQLException e) {
e.printStackTrace();
}
}
return androidDao;
}
@Override
public void close() {
super.close();
if (androidDao !=null) {
androidDao = null;
}
}
}
ContentProvider:
package com.example.hellojni;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
public class MyContentProvider extends ContentProvider{
private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
private static final int CODE_NOPARAM = 1;
private static final int CODE_PARAM = 2;
private static final String AUTHORITIES = "cn.siy.provider.database";
private static final String PATH_1 = "android";
private static final String PATH_2 = "android/#";
//集合类型,返回值前面一般是固定的,后面的值是自己添加的,也可以加上包路径
private static final String TYPE_ANDROIDS = "vnd.android.cursor.dir/" + "android";
//非集合类型数据,返回值前面一般是固定的,后面的值是自己添加的,也可以加上包路径
private static final String TYPE_ANDROID = "vnd.android.cursor.item/" + "android";
/**
* content://cn.siy.provider.database/android/1/name
*
* 其中content://是scheme Android规定必须是content
* cn.siy.provider.database 是Authority ContentProvider的唯一标示
* /android/1/name 是path 指定对什么数据进行操作(对android表的id为1的name字段操作)
*/
DataBaseHelper helper;
static{
matcher.addURI(AUTHORITIES, PATH_1, CODE_NOPARAM);
matcher.addURI(AUTHORITIES, PATH_2, CODE_PARAM);
}
@Override
public boolean onCreate() {
helper = DataBaseHelper.getHelper(getContext());
return true;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase sqLiteDatabase = helper.getWritableDatabase();
int count =-1;
switch (matcher.match(uri)) {
case CODE_NOPARAM:
count = sqLiteDatabase.delete(PATH_1, selection, selectionArgs);
break;
case CODE_PARAM:
long id = ContentUris.parseId(uri);
String where = "_id = " + id;
if (null != selection && !"".equals(selection.trim()))
{
where += " and " + selection;
}
count = sqLiteDatabase.delete(PATH_1, where, selectionArgs);
break;
default:
break;
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public String getType(Uri arg0) {
switch (matcher.match(arg0)) {
case CODE_NOPARAM:
return TYPE_ANDROIDS;
case CODE_PARAM:
return TYPE_ANDROID;
default:
break;
}
return null;
}
@Override
public Uri insert(Uri url, ContentValues values) {
SQLiteDatabase db = helper.getWritableDatabase();
long id = -1;
switch (matcher.match(url))
{
case CODE_NOPARAM:
// 若主键值是自增长的id值则返回值为主键值,否则为行号,但行号并不是RecNo列
id = db.insert(PATH_1, "name", values);
break;
default:
break;
}
if (id>0) {
Uri insertUri = ContentUris.withAppendedId(url, id);
getContext().getContentResolver().notifyChange(insertUri, null);
return insertUri;
}
return null;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteDatabase sqLiteDatabase = helper.getReadableDatabase();
Cursor cursor = null;
switch (matcher.match(uri)) {
case CODE_NOPARAM:
cursor = sqLiteDatabase.query(PATH_1, projection, selection, selectionArgs, null, null, sortOrder);
break;
case CODE_PARAM:
long id = ContentUris.parseId(uri); // 取得跟在URI后面的数字
String where = "_id = " + id;
if (null != selection && !"".equals(selection.trim()))
{
where += " and " + selection;
}
cursor = sqLiteDatabase.query(PATH_1, projection, where, selectionArgs, null, null, sortOrder);
break;
default:
break;
}
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
SQLiteDatabase sqLiteDatabase = helper.getWritableDatabase();
int count = 0;
switch (matcher.match(uri)) {
case CODE_NOPARAM:
count = sqLiteDatabase.update(PATH_1, values, selection, selectionArgs);
break;
case CODE_PARAM:
long id = ContentUris.parseId(uri);
String where = "_id = " + id;
if (null != selection && !"".equals(selection.trim()))
{
where += " and " + selection;
}
count = sqLiteDatabase.update(PATH_1, values, where, selectionArgs);
default:
break;
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testndk"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.hellojni.SiyActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider
android:exported="true"
android:name="com.example.hellojni.MyContentProvider"
android:authorities="cn.siy.provider.database">
</provider>
</application>
</manifest>
数据库的操作使用了ormlite框架。
首先我对ContentProvider中增删改查几个方法的参数解释一下吧,因为一开始我自己也是糊涂,这里记录一下防止下
次自己又忘记了。
1)delete(Uri uri, String selection, String[] selectionArgs);
第一个参数 uri:uri怎么解释呢?恩!就是每个内容提供者的唯一标示,用指定你访问的是哪一个内容提供者。
第二个参数 selecttion:他可以单独使用也可以和selectionArgs配合使用。先解释它怎么单独使用例如:
contentResolver.delete(Uri.parse("content://cn.siy.provider.database/android"), "_id in (14,13,12)", null);
上面语句的意思就是删除_id是12,13,14的记录,执行之后的结果
单独使用的时候他就相当于条件语句,放在where 之后。也可以传null表示删除所有。再看看它怎么和selectionArgs配合使用:
contentResolver.delete(Uri.parse("content://cn.siy.provider.database/android"), "_id in(?,?,?)", new String[]{"14","13","12"});
执行结果和上面的结果一样。selecttion你面有多少个“?”,selectionArgs里面就要有多少个数据进行相应的替换,特别注意顺序额!
第三个参数selectionArgs:他就是配合selecttion的,如果selecttion是空的,它也可以传null。
2)insert(Uri uri, ContentValues values)
第一个参数uri:同上不做解释。
第二个参数 values:他是一个类似map的数据结构,可以put进键值对,key是表结构的列名,value是列名对应的值,具体用法如:
ContentValues contentValues = new ContentValues();
contentValues.put("name", "Android-N");
contentValues.put("version", "7.0");
contentResolver.insert(Uri.parse("content://cn.siy.provider.database/android"), contentValues);
3)query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
第一个参数uri:同上不做解释。
第二个参数projection:它表示查询后要显示的列名,可以传null表示查询显示所有,类似如sql语句的“*”。
第三个参数selection:同上不解释。
第四个参数selectionArgs:同上不解释。
第五参数sortOrder:它是指按照什么顺序排序,相当于sql的order by。具体用法如:
Cursor cursor = contentResolver.query(Uri.parse("content://cn.siy.provider.database/android"), null, null, null, "_id desc");
4)update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
参数的意思都能在上面找到我就不说了。
要编写ContentProvider:
1,要继承要写一个类继承ContentProvider然后重写里面的方法,一般会有onCreate(),getType(),delete(),insert(),query(),update()。
2,指定一个唯一标示当前provider的uri。provider的uri的规则content://+Authority+path。content://是Android规定的不允许更改的,Authority自己指定作为provider的唯一标示,最好两级以上,何为两级以上呢?自己领悟!path是标示
操作对象一般表名什么。
举个例子吧:
content://cn.siy.provider.database/android/1/name
其中content://是scheme Android规定必须是content
cn.siy.provider.database 是Authority ContentProvider的唯一标示
/android/1/name 是path 指定对什么数据进行操作(对android表的id为1的name字段操作)
3,既然uri里面包含这么多信息,那么provider怎么知道呢?Android为我们提供UriMatcher这个类,它允许我们将定
义好的uri添加到其中。
private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
static{
matcher.addURI(AUTHORITIES, PATH_1, CODE_NOPARAM);
matcher.addURI(AUTHORITIES, PATH_2, CODE_PARAM);
}
UriMatcher.NO_MATCH是匹配失败返回的值为-1。CODE_NOPARAM表示匹配path_1返回的值,CODE_PARAM表
示path_2返回的值。其中“匹配”动作可以通过matcher.match(uri)方法实现,这样就可以通过不同的返回值来进行不同的操作了。
4,既然provider是的四大组件之一(Activity,receiver,service,provider),那么它也是要在AndroidManifest.xml注册的。
<provider
android:exported="true"
android:name="com.example.hellojni.MyContentProvider"
android:authorities="cn.siy.provider.database">
</provider>
authorities就是上面说的uri中的authorities,name就是ContentProvider的全类名,exported为true表示它对其他应用可
见。
要使用provider:
1,首先你得有ContentResolver,这个你一调用Activity的getContentResolver()得到。
2, 然后通过ContentResolver的增删改查方法就可以调用provider的增删改查方法了,参数名的意思上面有说。
3,Uri.parse("content://cn.siy.provider.database/android")把字符串编程uri
到此provider的简单实用就解释完了,不说了。
(4)AIDL
例子不知道怎么举了,那就直接上代码吧!
服务端:(注:服务端和客户端不是同一个应用)
IService.aidl
package com.example.mytest.zoomInImanage;
import com.example.mytest.zoomInImanage.Android;
interface IService{
/** 八种基本类型 shot 会报错额**/
String input1(byte arg1,/**shot arg2,**/int arg3,char arg4,boolean arg5,float arg6,double arg7,long arg8);
String input2(String arg1,CharSequence arg2);
/** 需要使用in、out或inout修饰。其中in表示这个值被客户端设置;out表示这个值被服务端设置;inout表示这个值既被客户端设置,又被服务端设置。 **/
Android input3(in List<String> arg1,in Map arg2);
/** 必须要导包 **/
String input4(in Android arg1);
}
Android.java(其实就是上面的Android类实现了Parcelable,哈哈...)
package com.example.mytest.zoomInImanage;
import android.os.Parcel;
import android.os.Parcelable;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
@DatabaseTable(tableName = "android")
public class Android implements Parcelable {
@DatabaseField(columnName = "_id", generatedId = true)
private Integer id;
@DatabaseField(columnName = "name")
private String name;
@DatabaseField(columnName = "version")
private String version;
public Android() {
}
public Android(String name, String version) {
this.name = name;
this.version = version;
}
public Android(Integer id,String name, String version) {
this.id = id;
this.name = name;
this.version = version;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel arg0, int arg1) {
// 注:Parcel中的数据是按顺序写入和读取的,即先被写入的就会先被读取出来
arg0.writeInt(id);
arg0.writeString(name);
arg0.writeString(version);
}
//该静态域是必须要有的,而且名字必须是CREATOR,否则会出错
public static final Parcelable.Creator<Android> CREATOR = new Creator<Android>() {
@Override
public Android[] newArray(int arg0) {
return new Android[arg0];
}
@Override
public Android createFromParcel(Parcel arg0) {
//从Parcel读取通过writeToParcel方法写入的Person的相关成员信息
return new Android(arg0.readInt(), arg0.readString(), arg0.readString());
}
};
}
Android.aidl(aidl传输的Parcelable对象,必须顶一个相应的aidl文件)
parcelable Android;
Myservice.java
package com.example.mytest.zoomInImanage;
import java.util.List;
import java.util.Map;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class MyService extends Service{
class MyBinder extends IService.Stub{
@Override
public String input1(byte arg1, int arg3, char arg4, boolean arg5, float arg6, double arg7, long arg8)
throws RemoteException {
return arg1+"-"+arg3+"-"+arg4+"-"+arg5+"-"+arg6+"-"+arg7+"-"+arg8+"-over";
}
@Override
public String input2(String arg1, CharSequence arg2) throws RemoteException {
return arg1+"-"+arg2+"-over";
}
@Override
public Android input3(List<String> arg1, Map arg2) throws RemoteException {
if (arg2.containsKey(1)) {
if (arg2.get(1) instanceof Android) {
return (Android)arg2.get(1);
}
}
return null;
}
@Override
public String input4(Android arg1) throws RemoteException {
return arg1.getName();
}
}
private MyBinder mybinder;
@Override
public void onCreate() {
super.onCreate();
Log.d("TAG", "onCreate");
mybinder = new MyBinder();
}
@Override
public IBinder onBind(Intent arg0) {
Log.d("TAG", "onBind");
return mybinder;
}
}
AndroidManifest.xml
<service android:name="com.example.mytest.zoomInImanage.MyService"
android:exported="true">
<intent-filter>
<!-- 指定调用AIDL服务的ID -->
<action android:name="com.siy.servicer" />
</intent-filter>
</service>
客户端:
Intent intent = new Intent("com.siy.servicer");
IService iservice;
bindService(intent, conn, Context.BIND_AUTO_CREATE);
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName arg0) {
}
@Override
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
Log.d("TAG", arg0+"");
iservice = IService.Stub.asInterface(arg1);
}
};
使用AIDL:
1,首先呢得写一个服务的aidl文件,里面定义一些需要实现的方法。
2,关于方法的参数:
①支持除了shot类型以为的基本类型(byte,char,int,boolean,float,long,double)
②支持String,CharSequence类型
③支持实现Parcelable序列化的类型
④支持List,Map,但是里面传输的类型必须是以上4种
3,如果传输Parcelable序列化的对象,必须定义相应的aidl文件,并且不要忘记在服务的aidl文件中导包
4,实现的服务类,必须在onBind返回服务的aidl的实现类的桩对象(也有人说是句柄对象,随便你叫什么),就是那个继承.Stub的对象。
5,在AndroidManifest.xml中注册。
6,在客户端绑定服务,用iservice = IService.Stub.asInterface(arg1)获取远程服务对象。注意哈,你的服务端的.aidl文件都要拷一份给客户端并且包名不能变。
(5)Messenger
例子不举了吧!
我还是看代码吧!我觉得代码最能让人理解。
MessageService:
public class MessageService extends Service{
public static final int FROMCLIENT = 123;
private Messenger service = new Messenger(new Handler(){
@Override
public void handleMessage(Message msg) {
Message serviceMessage = Message.obtain();
switch (msg.what) {
case FROMCLIENT:
serviceMessage.what = FROMCLIENT;
Android an = (Android)(msg.obj);
// serviceMessage.obj = an.getName();
// serviceMessage.arg1 = msg.arg1;
Bundle bundle = msg.getData();
Android andriod_1 = (Android) bundle.getSerializable("android_1");
Android android_2 = (Android) bundle.getSerializable("android_2");
Android android = new Android(andriod_1.getId() + android_2.getId(), andriod_1.getName() +
android_2.getName(), andriod_1.getVersion() + android_2.getVersion());
Bundle bundle_1 = new Bundle();
bundle_1.putSerializable("android", android);
serviceMessage.setData(bundle_1);
try {
msg.replyTo.send(serviceMessage);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
default:
break;
}
super.handleMessage(msg);
};
});
@Override
public IBinder onBind(Intent arg0) {
return service.getBinder();
}
}
AndroidManifest.xml
<service android:name="com.example.mytest.photowall.MessageService"
android:exported="true">
<intent-filter >
<action android:name="com.siy.messageservice"/>
</intent-filter>
</service>
client:
private static final int FROMCLIENT = 123;
private Messenger mServiceMessage;
private ServiceConnection messageConn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
mServiceMessage = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mServiceMessage = new Messenger(service);
Log.d("TAG", "连上了");
}
};
private Messenger client = new Messenger(new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case FROMCLIENT:
Bundle bundle = msg.getData();
Android android = (Android) bundle.getSerializable("android");
Log.d("TAG", "messenger:"+android);
break;
default:
break;
}
super.handleMessage(msg);
}
});
private void test_7(){
Message clientMessage = Message.obtain();
clientMessage.what = FROMCLIENT;
// clientMessage.obj = new Android(1, "andorid-n", "7.0");
// clientMessage.arg1 = 1;
Bundle bundle = new Bundle();
bundle.putSerializable("android_1", new Android(1,"andriod-1", "1.0"));
bundle.putSerializable("android_2", new Android(2,"android-2", "2.0"));
clientMessage.setData(bundle);
clientMessage.replyTo = client;
try {
mServiceMessage.send(clientMessage);
} catch (RemoteException e) {
e.printStackTrace();
}
}
使用messenger:
1,在服务器定一个Messenger 并以Handler为参数实例化它。
2,在AndroidManifest.xml注册它
3,在客户端也是用一个Messenger并以Handler参数实例化它进行通信的。
其实messenger的使用非常简单。但是他们通信所传递的对象如果是int型直接用户message.arg1 和message.arg2就
行了,如果是自定义对象不能用message.obj,而要使用message.setData(),而且我发现不能使用Parcelable对象要使
用Serializable,不知道是不是我的使用方式不对,反正我使用Parcelable老师报错的。
好了先写这里吧!