編輯:關於Android編程
最近在學習IPC進程間通信,在此記錄下AIDL的使用,並附上一個Demo:服務端每隔一分鐘添加一本書籍,客戶端通過進程間通信,獲取當前服務端的書籍列表,並且服務端對外開放添加、刪除等操作。
1、新建一個AIDLServer工程,創建一個Parcelable接口類Book
package com.aa.aidlserver;
import android.os.Parcel;
import android.os.Parcelable;
public class Book implements Parcelable {
public String name;
public String describe;
public Book(String name, String describe) {
this.name = name;
this.describe = describe;
}
protected Book(Parcel in) {
name = in.readString();
describe = in.readString();
}
//反序列化
public static final Creator CREATOR = new Creator() {
@Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
//序列化
parcel.writeString(name);
parcel.writeString(describe);
}
}
2、創建兩個aidl文件:Book.aidl和IBookManager.aidl
// Book.aidl package com.aa.aidlserver; parcelable Book;
// IBookManager.aidl
package com.aa.aidlserver;
import com.aa.aidlserver.Book;
interface IBookManager {
//獲取書本列表
List getBookList();
//添加書本
void addBook(in Book book);
//刪除書本
void deleteBook(in Book book);
}
注意:
其中Book.aidl用來聲明Book實現了Parcelable接口 因為在IBookManager中使用了Book參數,所以無論Book.java是否在同一個包名下,都必須進行一次import3、創建自定義Service,創建一個IBookManager.Stub對象,即一個Binder對象,重寫onBind方法返回這個對象。然後在AndroidManifest中聲明此Service,並加入action
package com.aa.aidlserver;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class AIDLService extends Service {
/**
* 書本列表
*/
private CopyOnWriteArrayList mBookList = new CopyOnWriteArrayList<>();
private Binder mBinder = new IBookManager.Stub() {
@Override
public List getBookList() throws RemoteException {
return mBookList;
}
@Override
public void addBook(Book book) throws RemoteException {
mBookList.add(book);
}
@Override
public void deleteBook(Book book) throws RemoteException {
mBookList.remove(0);
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(mBookList.size() == 0) {
mBookList.add(new Book("他們最幸福", "一個屌絲寫的書"));
mBookList.add(new Book("曉松奇談", "矮大緊寫的書"));
} else {
addBook();
}
return super.onStartCommand(intent, flags, startId);
}
/**
* 通過定時任務來添加書本信息
*/
private void addBook() {
Log.e("TAG", "Adding...");
int len = mBookList.size() + 1;
String name = "圖書" + len;
String describe = "這是第" + len + "本書";
Book book = new Book(name, describe);
mBookList.add(book);
}
}
4、在MainActivity中使用AlarmManager每隔一分鐘創建(打開)Service
package com.aa.aidlserver;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initAlarmManager();
}
/**
* 初始化定時任務
*/
private void initAlarmManager() {
Intent intent = new Intent();
// 設置Intent的Action 屬性
intent.setAction("com.aa.aidlserver.AIDLService");
// Android 5.0以上需要設置包名
intent.setPackage("com.aa.aidlserver");
//創建一個PendingIntent對象,包含了startService操作
PendingIntent pi = PendingIntent.getService(this, 0,intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
long intervalMillis = 60 * 1000;
//創建一個系統級定時器,即使熄屏狀態也會每隔一分鐘啟動一次Service添加書本(注:部分定制系統定時器不准)
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), intervalMillis, pi);
}
}
5、在app的build.gradle文件的android節點中添加以下代碼,可解決找不到Book類的問題
sourceSets {
main {
manifest.srcFile 'src/main/AndroidManifest.xml'
java.srcDirs = ['src/main/java', 'src/main/aidl']
resources.srcDirs = ['src/main/java', 'src/main/aidl']
aidl.srcDirs = ['src/main/aidl']
res.srcDirs = ['src/main/res']
assets.srcDirs = ['src/main/assets']
}
}
至此服務端就開發完畢了,相比之下,客戶端的就簡單一些。
1、新建一個AIDLClient工程,將AIDLServer工程的app\src\main\aidl目錄拷貝到AIDLClient工程的app\src\main目錄下,不需任何修改(注意這裡的包名、文件都與AIDLServer是一致的)

2、服務端每隔一分鐘會添加一本書,所以在客戶端MainActivity中獲取當前服務端書本列表並顯示,也可進行添加、刪除等操作
package com.aa.aidlclient;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import com.aa.aidlserver.Book;
import com.aa.aidlserver.IBookManager;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private ListView mListView;
private ArrayAdapter mAdapter;
private List mBooks = new ArrayList<>();
private Button btnLoadmore, btnAdd, btnDetele;
private IBookManager mIBookManager;
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
//Service已連接
mIBookManager = IBookManager.Stub.asInterface(iBinder);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
//Service已斷開
mIBookManager = null;
}
};
private void toast(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
Log.e("AA", "收到Log:" + msg);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = (ListView) findViewById(R.id.lv_main);
btnLoadmore = (Button) findViewById(R.id.btn_main_loadmore);
btnLoadmore.setOnClickListener(this);
btnAdd = (Button) findViewById(R.id.btn_main_add);
btnAdd.setOnClickListener(this);
btnDetele = (Button) findViewById(R.id.btn_main_delete);
btnDetele.setOnClickListener(this);
bindAIDLService();
}
@Override
protected void onDestroy() {
unbindAIDLService();
super.onDestroy();
}
/**
* 綁定AIDL服務
*/
private void bindAIDLService() {
Intent intent = new Intent("com.aa.aidlserver.AIDLService");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Android 5.0以上需要設置包名
intent.setPackage("com.aa.aidlserver");
bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
}
/**
* 解綁AIDL服務
*/
private void unbindAIDLService() {
if(mIBookManager != null) {
unbindService(mServiceConnection);
}
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_main_loadmore:
//加載更多
try {
List books = mIBookManager.getBookList();
if(books != null && books.size() > 0) {
if(mBooks.size() > 0) {
mBooks.clear();
}
//解析數據
for(Book book : books) {
mBooks.add("Name:" + book.name + " --- Describe:" + book.describe);
}
//填充數據
mAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, android.R.id.text1, mBooks);
mListView.setAdapter(mAdapter);
}
} catch (RemoteException e) {
e.printStackTrace();
}
break;
case R.id.btn_main_add:
//新增圖書
int len = mBooks.size() + 1;
String name = "圖書" + len;
String describe = "這是第" + len + "本書";
Book book = new Book(name, describe);
try {
mIBookManager.addBook(book);
mBooks.add("Name:" + book.name + " --- Describe:" + book.describe);
mAdapter.notifyDataSetChanged();
} catch (RemoteException e) {
e.printStackTrace();
}
break;
case R.id.btn_main_delete:
//刪除圖書
if(mBooks.size() > 0) {
try {
Book book1 = mIBookManager.getBookList().get(0);
mIBookManager.deleteBook(book1);
mBooks.remove(0);
mAdapter.notifyDataSetChanged();
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
toast("已經沒有書可以刪除了");
}
break;
}
}
}
3、客戶端也需要在app的build.gradle文件的android節點中添加以下代碼,解決找不到Book類的問題
sourceSets {
main {
manifest.srcFile 'src/main/AndroidManifest.xml'
java.srcDirs = ['src/main/java', 'src/main/aidl']
resources.srcDirs = ['src/main/java', 'src/main/aidl']
aidl.srcDirs = ['src/main/aidl']
res.srcDirs = ['src/main/res']
assets.srcDirs = ['src/main/assets']
}
}
其實,AIDL說簡單也不簡單,難也並不難,還是需要根據實際需求來做的。
Github AIDLServer
Github AIDLClient
Android中Fragment管理及重疊問題的解決方法
一、Fragment介紹fragment在3.0被引入以後,項目使用fragment越來越多,特別是主界面是底部tab頁點擊切換更換內容,當然啦, Fragment 在項
Android-Universal-Image-Loader 圖片異步加載類庫的使用
開發App過程中,免不了要進行網絡請求操作進行數據交換,比如下載圖片,如果自己寫一個下載圖片的類進行操作的話,要考慮太多太多內容,必須線程池,內存溢出,圖片磁盤緩存操作,
Android.Camera2相機超詳細講解
在API21中Google就發布了Camera2類來取代Camera類,那麼這個Camera2類到底改變了那些地方呢,我們來看官方的說法:Camera2 APISuppo
Android App發布到應用市場的流程
AndroidApp上架所需文件上架准備App文件:1.安裝包2.應用商標:圖片格式PNG,大小512*512,小於800KB。3.應用截圖(4~6張):圖片格式JPG或