編輯:關於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.Creator CREATOR = 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();
List resolveInfo = 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);
Android實現跟隨手指拖動並自動貼邊的View樣式(實例demo)
效果圖代碼/** * 根據手指拖動的當前位置,自動貼邊的View */public class DragView extends ImageView implements
Android Studio下 NDK開發流程
NDK環境搭建1.在android studio中新建一個測試項目,並進行配置如果已經安裝了ndk可以在項目的根目錄右鍵open Module Settings中看到你配
白話開發——自己動手編譯Android源碼
簡單的介紹了Android Studio代碼調試的一些技巧.現在呢,我們來談談android源碼編譯的一些事.(俺認為,作為android developer人人都應該有
Android訂票系統訂票功能實現(特效點擊按鈕實現票數自動加減1)
要實現的效果是點擊加按鈕就購買分數自動加一,同時計算合計的總計 先共享一份colors.xml的數據,比較全面,可以根據需要添加