編輯:關於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 CreatorCREATOR = 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 { //獲取書本列表 ListgetBookList(); //添加書本 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 CopyOnWriteArrayListmBookList = 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 ArrayAdaptermAdapter; 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
一、Fragment介紹fragment在3.0被引入以後,項目使用fragment越來越多,特別是主界面是底部tab頁點擊切換更換內容,當然啦, Fragment 在項
開發App過程中,免不了要進行網絡請求操作進行數據交換,比如下載圖片,如果自己寫一個下載圖片的類進行操作的話,要考慮太多太多內容,必須線程池,內存溢出,圖片磁盤緩存操作,
在API21中Google就發布了Camera2類來取代Camera類,那麼這個Camera2類到底改變了那些地方呢,我們來看官方的說法:Camera2 APISuppo
AndroidApp上架所需文件上架准備App文件:1.安裝包2.應用商標:圖片格式PNG,大小512*512,小於800KB。3.應用截圖(4~6張):圖片格式JPG或