AIDL
简介
AIDL,全称是Android Interface Define Language,即安卓接口定义语言,可以实现安卓设备中进程之间的通信(Inter Process Communication, IPC)。安卓中的服务分为2类:本地服务(网络下载大文件,音乐播放器,后台初始化数据库的操作);远程服务(远程调用支付宝进程的服务…)
使用:
进程之间的通信
步骤
(1).main里创建文件夹名:aidl,之后右击new—>AIDL(默认名:IMyAidlInterface.aidl)
(2).在接口里写方法
// IMyAidlInterface.aidl
package com.example.day16_practice_service;
// Declare any non-default types here with import statements
interface IMyAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and go_back values in AIDL.
*/
// void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
// double aDouble, String aString);
int plus(int id,int add);
int reduce(int id,int reduce);
int show(int id);
}
(3).Rebuild Project---->自动生成一个Java文件:E:\AndroidStudioProjects\Month02\day16_practice_service\build\generated\aidl_source_output_dir\debug\compileDebugAidl\out\com\example\day16_practice_service\IMyAidlInterface.java
(4).数据提供
public class MySQLite extends SQLiteOpenHelper {
public MySQLite(Context context) {
super(context, "practice", null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table users (id Integer primary key autoincrement,name varchar(30),balance Double)");
db.execSQL("insert into users values (null,?,?)",new String[]{"小明","3500000"});
db.execSQL("insert into users values (null,?,?)",new String[]{"小张","3000000"});
db.execSQL("insert into users values (null,?,?)",new String[]{"小李","3800000"});
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
服务
public class MyService extends Service {
MySQLite mySQLite;
SQLiteDatabase database;
//重写方法中要执行的具体操作
IBinder binder = new IMyAidlInterface.Stub() {
@Override
public int plus(int id, int add) throws RemoteException {
Cursor cursor = database.query("users", null, "id = ?", new String[]{id+""}, null, null, null, null);
double balance = 0;
if (cursor.moveToNext()){
balance = cursor.getDouble(cursor.getColumnIndex("balance"));
}else{
return -1;
}
ContentValues values = new ContentValues();
values.put("balance",add+balance);
int users = database.update("users", values, "id = ?", new String[]{id + ""});
return users;
}
@Override
public int reduce(int id, int reduce) throws RemoteException {
Cursor cursor = database.query("users", null, "id = ?", new String[]{id+""}, null, null, null, null);
double balance = 0;
if (cursor.moveToNext()){
balance = cursor.getDouble(cursor.getColumnIndex("balance"));
}else{
return -1;
}
ContentValues values = new ContentValues();
if (balance > reduce){
values.put("balance",balance-reduce);
}else {
return -2;
}
int users = database.update("users", values, "id = ?", new String[]{id + ""});
return users;
}
@Override
public int show(int id) throws RemoteException {
Cursor cursor = database.query("users", null, "id = ?", new String[]{id+""}, null, null, null, null);
double balance;
if (cursor.moveToNext()){
balance = cursor.getDouble(cursor.getColumnIndex("balance"));
}else {
return -1;
}
return (int)balance;
}
};
@Override
public void onCreate() {
super.onCreate();
mySQLite = new MySQLite(this);
database = mySQLite.getWritableDatabase();
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
}
清单文件注册:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.day16_practice_service">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyService"
android:exported="true">
<intent-filter>
<action android:name="com.bw.practice"></action>
</intent-filter>
</service>
</application>
</manifest>
(5).另一个App中:
创建一个与上一个App中一模一样的aidl,步骤同上,注意 包名必须相同
public class MainActivity extends AppCompatActivity {
Button btn1,btn2,btn3;
IMyAidlInterface iMyAidlInterface;
ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
iMyAidlInterface = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn1 = findViewById(R.id.add1);
btn2 = findViewById(R.id.reduce);
btn3 = findViewById(R.id.show);
btn3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
int show = iMyAidlInterface.show(1);
Toast.makeText(MainActivity.this, ""+show, Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
int reduce = iMyAidlInterface.reduce(1, 2000);
if (reduce == -1){
Toast.makeText(MainActivity.this, "无此id", Toast.LENGTH_SHORT).show();
return;
}
if (reduce == -2){
Toast.makeText(MainActivity.this, "余额不足", Toast.LENGTH_SHORT).show();
return;
}
Toast.makeText(MainActivity.this, "成功", Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
int plus = iMyAidlInterface.plus(1, 30000);
if (plus == -1){
Toast.makeText(MainActivity.this, "无此id", Toast.LENGTH_SHORT).show();
return;
}
Toast.makeText(MainActivity.this, "成功", Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
Intent intent = new Intent();
intent.setAction("com.bw.practice");
intent.setPackage("com.example.day16_practice_service");
bindService(intent,connection,BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(connection);
}
}
先启动数据提供端,再启动数据修改端
Messager
Messager 信使,能够完成跨进程通信。
Messager的原理
Messager的2个构造方法:分别以handler和Ibinder为参数
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
public Messenger(IBinder target) {
mTarget = IMessenger.Stub.asInterface(target);
}
我们可以在客户端发送一个Message给服务端,在服务端的handler中会接收到客户端的消息,然后进行对应的处理,处理完成后,再将结果等数据封装成Message,发送给客户端,客户端的handler中会接收到处理的结果。
特点
·客户端和服务端发送的都是message
·使用handler接受消息(客户端和服务端都是)
·不需要编写aidl文件
服务端:
public class MyService extends Service {
//服务端信使对象,可以接受客户端发来的消息
Messenger messenger=new Messenger(new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//接受客户端发来的消息
Bundle data = msg.getData();
String data1 = data.getString("data");
Toast.makeText(MyService.this, "接收到信息"+data1, Toast.LENGTH_SHORT).show();
}
});
@Override
public IBinder onBind(Intent intent) {
return messenger.getBinder();
}
}
清单文件注册
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.day16_messager_server">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyService" android:exported="true">
<intent-filter>
<action android:name="com.bawei.1704.aa"></action>
</intent-filter>
</service>
</application>
</manifest>
客户端:
public class MainActivity extends AppCompatActivity {
ServiceConnection connection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//获得服务端的信使对象
Messenger messenger = new Messenger(service);
//客户端向服务端发送消息
Message message = new Message();
//打包发送(注意)
Bundle bundle = new Bundle();
bundle.putString("data","服务器你好");
message.setData(bundle);
try {
messenger.send(message);
Toast.makeText(MainActivity.this, "客户端发送成功", Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent();
intent.setAction("com.bawei.1704.aa");
intent.setPackage("com.example.day16_messager_server");
bindService(intent,connection,BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(connection);
}
}