现在的位置: 首页 > 综合 > 正文

Android学习之远程绑定调用service

2013年11月26日 ⁄ 综合 ⁄ 共 6240字 ⁄ 字号 评论关闭

最近今天在学习service控件,前面的后台service和绑定本地控件的service的很容易理解,几乎没遇到什么问题,但看到远程调用service的时候模仿书上的例题,结果发现竟然得不到想要的结果,把书上的例子源码弄进去,还是会有问题,于是经过好几天的自己摸索和网上参考一些资料,主要得到帮助的来自http://www.cnblogs.com/TerryBlog/archive/2010/08/24/1807605.html         http://ericchan2012.iteye.com/blog/1554197 这2个网址。接下来直接进入正题,对这几天对远程绑定调用service的学习结果。

远程绑定调用service主要是用来不同进程的信息共享。就比如服务器和客户端,在服务器端设置好一个service提供方法或信息,然后客户端可以直接调用服务器端service提供方法或信息。这里有个前提是客户端必须有和服务器端一份一样的AIDL,然后服务器端在客户端使用的系统上有注册过(也就是安装运行过一次),之后客户端就可以远程绑定调用服务器端的service了。

具体的步骤如下:

1.首先,是服务器的

  1)创建一个android应用工程  

   

  2)  在主Aitivity所在的包里新建个AIDL文件,这是ADT会自动帮你在gen目录下生成一个和AIDL文件同名的JAVA文件(这里的AidlService.java是下一步骤生成的,这里可以先忽略)

  

  3)如上图所示,创建一个用来使用service的类(AidlService.java)

  具体每个文件的代码如下:

  AidlServerActivity.java

 

package com.ds.server;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class AidlServerActivity extends Activity {
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		Button bt = (Button) findViewById(R.id.bt);
		bt.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Intent service = new Intent(AidlServerActivity.this,
						AidlService.class);
				startService(service);
				Toast.makeText(AidlServerActivity.this, "service started",
						Toast.LENGTH_LONG).show();
			}   

		});  

	}
}

IAidlService.aidl

package com.ds.server;
interface IAidlService {  
    int getType(); 
}  

 AidlService.java

package com.ds.server;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class AidlService extends Service {
	private boolean unrunnable;
	private int count;

	private class MyBinder extends IAidlService.Stub {

		@Override
		public int getType() throws RemoteException {
			// TODO Auto-generated method stub
			return 100;
		}
	}
	private void Log(String str) { 
		Log.d("AidlService", "------ " + str + "------");
	}

	@Override
	public void onCreate() {
		super.onCreate();
		/*
		new Thread(new Runnable(){
			@Override
			public void run(){
				while(!unrunnable){
					try{
						Thread.sleep(1000);
					}catch(InterruptedException e){
					}
					count++;
					Log.v("AidlService","count:"+count);
				}		
			}
		}).start();
		*/
		Log.v("RemoteCountService","onCreate");
		Log("service create");
		
	}
/*
	@Override
	public void onStart(Intent intent, int startId) {
		Log("service start id=" + startId);
	}
*/
	@Override
	public IBinder onBind(Intent t) {
		Log("service on bind");
		return new MyBinder();
	}

	@Override
	public void onDestroy() {
		Log("service on destroy");
		unrunnable=true;
		super.onDestroy();
	}
	/*

	@Override
	public boolean onUnbind(Intent intent) {
		Log("service on unbind");
		return super.onUnbind(intent);
	}

	public void onRebind(Intent intent) {
		Log("service on rebind");
		super.onRebind(intent);
	}
	*/

}

布局文件AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.ds.server"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".AidlServerActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".AidlService"
            android:enabled="true"
            android:process=":remote" >
            <intent-filter>

                <!-- AIDL完整路径名。必须指明,客户端能够通过AIDL类名查找到它的实现类 -->
                <action android:name="com.ds.server.IAidlService" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </service>
    </application>

</manifest>

这里,服务器端的工作做好了,接下来是客户端的工作。

2.接着,是客户端的:

 1)首先,创建一个工程

 

 2)接着,把服务器端的一些文件拷贝过来(创建com.ds.server这个包,然后往里面复制进入如下图的服务器端的文件(IAidlService.java)

 

下面是个文件的内容

    AidlClientActivity.java

   

package com.ds.client;

import com.ds.server.IAidlService;

import android.app.Activity;
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.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class AidlClientActivity extends Activity {

	IAidlService iservice; 
	int count;

	private ServiceConnection connection = new ServiceConnection() {

		public void onServiceConnected(ComponentName name, IBinder service) {
			// TODO Auto-generated method stub
			// 浠庤繙绋媠ervice涓幏寰桝IDL瀹炰緥鍖栧璞�			
			iservice = IAidlService.Stub.asInterface(service);
			Log.i("Client","Bind Success:" + iservice);
		}  

		public void onServiceDisconnected(ComponentName name) {
			// TODO Auto-generated method stub
			iservice = null;
			Log.i("Client","onServiceDisconnected");
		}
	};  
  
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {  
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		final TextView tv = (TextView) findViewById(R.id.tv);
		Button bt = (Button) findViewById(R.id.bt);
		bt.setOnClickListener(new OnClickListener() {
			

			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				Intent service = new Intent(IAidlService.class.getName());
				bindService(service, connection, BIND_AUTO_CREATE);
				if (iservice != null) {  
					try {
						Log.v("AidlClientActivity","oncreate"+iservice.getType()+" "+count);
					} catch (RemoteException e) {
						e.printStackTrace();
					}
				}
				else{
					count++;
				}
			}

		});

	}
}

 AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.ds.client"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".AidlClientActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

这样客户端的工作也算完了,但这里我还想说下一个问题。

你可能会看到在客户端的Activity文件里,有个count的变量,觉得是多余的,但这是为了说明下面这个问题的需要。

最开始的count是0,然后我运行客户端后,鼠标左击bind按钮,会发现LogCat的verbose窗口会显示

为什么没有执行 Log.v("AidlClientActivity","oncreate"+iservice.getType()+" "+count);这一句,然后我再点击下bind

终于出现想要的结果,这里你就会发现count变成1了,也就是之前执行过一次count+1了,这就说明了,第一次只是绑定,返回的 iservice是null,第二次以上才会返回对象。

到这里就是我之前一直错误的地方,是理解错了,我之前写的程序没有按钮,是直接启动客户端后就绑定调用service,由于没有按钮不能多次按,也就会造成得不到想要的结果了。这里总算明白它的一些运行机制了,先写到这里,后面有什么新发现会及时更新。

抱歉!评论已关闭.