編輯:關於Android編程
public interface IController { public User getUser(int index); }
public class User { private int age; private String name; public User(int age, String name) { super(); this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }第二步:創建本地service
public class MyService extends Service { public MyBinder mBinder = new MyBinder(); @Override public IBinder onBind(Intent intent) { return mBinder; } public class MyBinder extends Binder implements IController{ @Override public User getUser(int index) { // 這裡返回查詢的結果 return new User(20, "panpan"); } } }第三步:綁定/解綁服務
public class TwoActivity extends Activity { private IController con; private MyConn conn; private TextView tv; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_two); tv = (TextView) findViewById(R.id.tv); Intent service = new Intent(getApplicationContext(), MyService.class); conn = new MyConn(); bindService(service, conn, BIND_AUTO_CREATE); } public void two(View v){ User user = con.getUser(1); tv.setText(user.getName()+":"+user.getAge()+"歲"); } private class MyConn implements ServiceConnection{ @Override public void onServiceConnected(ComponentName name, IBinder service) { //綁定本地服務可以強制轉換,綁定遠程服務不可以,後面有講 con = (IController) service; } @Override public void onServiceDisconnected(ComponentName name) { } } @Override protected void onDestroy() { super.onDestroy(); unbindService(conn);//一定不要忘記這一步 } }最後不要忘記在AndroidManifest中注冊service
以上代碼很簡單,不做解釋
我們以兩個Android工程來模擬客服端和服務端程序
public interface IController { public User getUser(int index); }創建一個實體類,實現Parcelable接口
public class User implements Parcelable { private int age; private String name; public User(int age, String name) { super(); this.age = age; this.name = name; } public User(Parcel in) { age = in.readInt(); name = in.readString(); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(age); dest.writeString(name); } public static final Parcelable.CreatorCREATOR = new Parcelable.Creator () { public User createFromParcel(Parcel in) { return new User(in); } public User[] newArray(int size) { return new User[size]; } }; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
在Navigator視圖中將接口IController.java後綴名.Java修改為.aidl(包視圖修改不了)
修改好後切回包視圖(Package Explorer),IController.aidl報錯
根據提示把兩個public刪掉並為實體類User加上描述文件,在User類所在包右鍵->New->File,創建同名的.aidl文件,即:User.aidl
User.aidl的內容就兩行
此時可以發現gen目錄下自動產生了IController.aidl的Java語言解釋類IController.java
內容如下
package com.ipjmc.scroller.contro; public interface IController extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.ipjmc.scroller.contro.IController { private static final java.lang.String DESCRIPTOR = "com.ipjmc.scroller.contro.IController"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.ipjmc.scroller.contro.IController interface, * generating a proxy if needed. */ public static com.ipjmc.scroller.contro.IController asInterface(android.os.IBinder obj) { if ((obj==null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin!=null)&&(iin instanceof com.ipjmc.scroller.contro.IController))) { return ((com.ipjmc.scroller.contro.IController)iin); } return new com.ipjmc.scroller.contro.IController.Stub.Proxy(obj); } @Override public android.os.IBinder asBinder() { return this; } @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_getUser: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); com.ipjmc.scroller.entity.User _result = this.getUser(_arg0); reply.writeNoException(); if ((_result!=null)) { reply.writeInt(1); _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { reply.writeInt(0); } return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.ipjmc.scroller.contro.IController { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } @Override public com.ipjmc.scroller.entity.User getUser(int index) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); com.ipjmc.scroller.entity.User _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(index); mRemote.transact(Stub.TRANSACTION_getUser, _data, _reply, 0); _reply.readException(); if ((0!=_reply.readInt())) { _result = com.ipjmc.scroller.entity.User.CREATOR.createFromParcel(_reply); } else { _result = null; } } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_getUser = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); } public com.ipjmc.scroller.entity.User getUser(int index) throws android.os.RemoteException; }創建服務端service
public class MyService extends Service { public MyBinder mBinder = new MyBinder(); @Override public IBinder onBind(Intent intent) { return mBinder; } // 繼承Stub就可以了,因為在IController.java中Stub就extends android.os.Binder 並且implements com.ipjmc.scroller.contro.IController,是不是覺得和綁定本地服務的時候有點像? public class MyBinder extends Stub{ @Override public User getUser(int index) { // 這裡返回查詢的結果 return new User(20, "panpan"); } } }在AndroidManifest中注冊service時添加過濾器intent-filter,因為跨進程訪問service我們使用隱私意圖
到此,服務端coding完成
再來看看客戶端代碼:
第一步:拷貝服務端以下內容到客戶端src下(帶包拷貝)
像這樣
然後在Activity中綁定遠程服務
public class MainActivity extends Activity { private TextView tv; private MyConn conn; private IController controller; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) findViewById(R.id.tv); Intent intent = new Intent("com.ipjmc.scroller.serveice.MyService"); conn = new MyConn(); bindService(intent, conn, BIND_AUTO_CREATE); } public class MyConn implements ServiceConnection{ @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub controller = Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { } } @Override protected void onDestroy() { super.onDestroy(); unbindService(conn); } public void two(View v){ try { User user = controller.getUser(1); tv.setText(user.getName()+":"+user.getAge()+"歲"); } catch (RemoteException e) { e.printStackTrace(); } } }客戶端coding完成,但是需要注意的是,在Android5.0及以後,Android系統出於安全考慮,禁止隱士調用方式,程序運行報錯:java.lang.IllegalArgumentException: Service Intent must be explicit,網上搜索到的解決方法:
//添加一個方法 public static Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) { // Retrieve all services that can match the given intent PackageManager pm = context.getPackageManager(); ListresolveInfo = pm.queryIntentServices(implicitIntent, 0); // Make sure only one match was found if (resolveInfo == null || resolveInfo.size() != 1) { return null; } // Get component info and create ComponentName ResolveInfo serviceInfo = resolveInfo.get(0); String packageName = serviceInfo.serviceInfo.packageName; String className = serviceInfo.serviceInfo.name; ComponentName component = new ComponentName(packageName, className); // Create a new intent. Use the old one for extras and such reuse Intent explicitIntent = new Intent(implicitIntent); // Set the component to be explicit explicitIntent.setComponent(component); return explicitIntent; }
Intent i = new Intent("com.ipjmc.scroller.serveice.MyService"); Intent intent = new Intent(createExplicitFromImplicitIntent(this,i)); conn = new MyConn(); bindService(intent, conn, BIND_AUTO_CREATE);
效果圖代碼/** * 根據手指拖動的當前位置,自動貼邊的View */public class DragView extends ImageView implements
NDK環境搭建1.在android studio中新建一個測試項目,並進行配置如果已經安裝了ndk可以在項目的根目錄右鍵open Module Settings中看到你配
簡單的介紹了Android Studio代碼調試的一些技巧.現在呢,我們來談談android源碼編譯的一些事.(俺認為,作為android developer人人都應該有
要實現的效果是點擊加按鈕就購買分數自動加一,同時計算合計的總計 先共享一份colors.xml的數據,比較全面,可以根據需要添加