- 论坛徽章:
- 0
|
继续接上文。点击主界面上的“bind启动Service”后,进入第二个副界面。第二个副界面我使用ListView来实现和用户的交互,并且能实时获取服务中提供的数值将其显示在界面上。该界面的布局文件为bind.xml其内容如下:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- <RelativeLayout android:id="@+id/RelativeLayout02"
- android:paddingTop="21.0px"
- android:paddingBottom="10.0px"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="15.0px"
- android:layout_marginTop="62.0px"
- android:layout_marginRight="15.0px">
- <ListView android:id="@+id/listView1"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent">
- </ListView>
- <TextView android:id="@+id/bindtext"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_below="@+id/listView1"
- android:gravity="center"
- />
- </RelativeLayout>
- </LinearLayout>
在这里我使用了RelativeLayout布局,因为如果还用LinerLayout布局的话就不能正常显示TextView了。界面的类我命名为bindStart.java,在这里碰到了难题,就是如何更新显示的内容。我的想法就是使用一个线程,每一秒中从Service那里获取数字并显示出来。但是系统却频频报错。向别人提问后才知道对于Activity界面的更新只有主线程才可以,别的线程一律不允许碰。那么要告诉主线程更新显示怎么办呢?这就要用到Handler类,Handler类可以说是用来实现线程间的通信。通过一个线程获取数据并发信息给主线程,主线程收到信息后按要求更新显示的内容。类的内容为:
- package com.test;
- import android.app.Activity;
- import android.content.ComponentName;
- import android.content.Context;
- import android.content.Intent;
- import android.content.ServiceConnection;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.IBinder;
- import android.os.Message;
- import android.util.Log;
- import android.view.View;
- import android.widget.AdapterView;
- import android.widget.AdapterView.OnItemClickListener;
- import android.widget.ArrayAdapter;
- import android.widget.ListView;
- import android.widget.TextView;
- import android.widget.Toast;
- public class bindStart extends Activity {
- private final static String TAG="bindStart";
- ListView listView;
- TextView textView;
- ArrayAdapter adapter;
- bindService bindservice;
- int num;
- int act;
- //更新显示用的线程
- fresh freshtext;
- public void onCreate(Bundle savedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.bind);
- listView=(ListView)findViewById(R.id.listView1);
- textView = (TextView)findViewById(R.id.bindtext);
- textView.setText(num+"");
- //设定list的背景色,否则显示不出来
- int mycolor=getResources().getColor(R.color.bachgroud);
- listView.setBackgroundColor(mycolor);
- //获得显示的内容
- adapter=ArrayAdapter.createFromResource(this.getApplicationContext(), R.array.actions,
- android.R.layout.simple_spinner_dropdown_item);
- listView.setAdapter(adapter);
- freshtext=new fresh();
- //开始bind
- Log.d(TAG, "connecting.....");
- Intent intent = new Intent("com.test.bindService");
- bindService(intent, sc, Context.BIND_AUTO_CREATE);
- //对list添加点击事件响应
- listView.setOnItemClickListener(new OnItemClickListener(){
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- switch(position){
- case 0:
- Toast.makeText(getApplicationContext(), "啥也不做", Toast.LENGTH_SHORT).show();
- break;
- case 1:
- act=1;
- start(act);
- Toast.makeText(getApplicationContext(), "启动服务", Toast.LENGTH_SHORT).show();
- break;
- case 2:
- act=2;
- start(act);
- Toast.makeText(getApplicationContext(), "暂停服务", Toast.LENGTH_SHORT).show();
- break;
- case 3:
- act=3;
- start(act);
- stop();
- break;
- }
- }
- });
- }
- private void start(int act) {
- Intent intent=new Intent("com.test.bindService");
- Bundle bundle=new Bundle();
- bundle.putInt("act", act);
- intent.putExtras(bundle);
- startService(intent);
- Log.v("start","startbindservice");
- //如果当前有更新线程在运行,首先结束它
- if(freshtext.running){
- freshtext.running=false;
- }
- //重新启动更新线程
- freshtext=new fresh();
- freshtext.running=true;
- new Thread(freshtext).start();
- }
- public void stop() {
- if(freshtext.running){
- freshtext.running=false;
- }
- this.unbindService(sc);
- this.finish();
- }
- class fresh implements Runnable{
- Boolean running=false;
- @Override
- public void run() {
- while(running){
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- //获取服务中产生的数字
- num =bindservice.get();
- //通过handler发消息给主线程,更新显示的内容
- Message msg=new Message();
- msg.what=1;
- h.sendMessage(msg);
- Log.d(TAG,"num is :"+num);
- }
- }
- }
- ServiceConnection sc=new ServiceConnection(){
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- bindservice=((bindService.myBinder)service).getService();
- Log.d(TAG, "in onServiceConnected");
- }
- @Override
- public void onServiceDisconnected(ComponentName name) {
- bindservice=null;
- }
- };
- /*
- * 主线程处理收到的信息
- */
- Handler h=new Handler(){
- public void handleMessage(Message msg){
- Log.d(TAG,"msg is "+msg.toString());
- switch(msg.what){
- case 1:
- textView.setText(num+"");
- break;
- }
- }
- };
- }
接下来当然是服务类了,没有什么特别之处,还是每秒钟对变量加一。
- package com.test;
- import android.app.Service;
- import android.content.Intent;
- import android.os.Binder;
- import android.os.Bundle;
- import android.os.IBinder;
- import android.util.Log;
- public class bindService extends Service {
- private final static String TAG="bindService";
- private IBinder binder=new myBinder();
- private int n=0;
- private count thread;
- @Override
- public IBinder onBind(Intent intent) {
- // TODO Auto-generated method stub
- return binder;
- }
- public class myBinder extends Binder{
- public bindService getService(){
- return bindService.this;
- }
- }
- public int get(){
- return n;
- }
- public void onCreate(){
- super.onCreate();
- Log.d(TAG,"onCreate");
- thread=new count();
- }
- public void onStart(Intent intent, int startId){
- Log.d(TAG,"onstart");
- if(intent!=null){
- Bundle budle=intent.getExtras();
- int act=budle.getInt("act");
- switch(act){
- case 1:
- start();
- break;
- case 2:
- stop();
- break;
case 3: finsish();
} } }
private void finsish() { thread.setPause(true); stopSelf();
}
- class count extends Thread{
- private boolean pause=false;
- public void setPause(boolean tof){
- pause=tof;
- }
- public boolean getPauseStatues(){
- return pause;
- }
- public void run(){
- while(!pause){
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- n++;
- Log.d(TAG,"n is:"+n);
- }
- }
- }
- private void stop() {
- thread.setPause(true);
- }
- private void start() {
- stop();
- if(thread.getPauseStatues()==true){
- thread=new count();
- thread.setPause(false);
- }
- thread.start();
- Log.d(TAG,String.valueOf(thread.getPauseStatues()));
- }
- }
该界面的显示如下图所示:最下面的数字每秒钟会更新一次。

最后就是远程Service了,使用了AIDL接口实现Activity和Service之间的通信,在这个界面中我使用单选按钮来和用户就行交互。布局文件为remote.xml
- <?xml version="1.0" encoding="utf-8"?>
-
<LinearLayout
-
xmlns:android="http://schemas.android.com/apk/res/android"
-
android:orientation="vertical"
-
android:layout_width="fill_parent"
-
android:layout_height="fill_parent">
-
<RadioGroup
-
android:id="@+id/radioGroup1"
-
android:layout_width="wrap_content"
-
android:layout_height="wrap_content"
-
android:gravity="center">
-
<RadioButton
-
android:layout_width="wrap_content"
-
android:id="@+id/radio0"
-
android:layout_height="wrap_content"
-
android:text="@string/do_nothing"
-
android:checked="true">
-
</RadioButton>
-
<RadioButton
-
android:layout_width="wrap_content"
-
android:id="@+id/radio1"
-
android:layout_height="wrap_content"
-
android:text="@string/start">
-
</RadioButton>
-
<RadioButton
-
android:layout_width="wrap_content"
-
android:id="@+id/radio2"
-
android:layout_height="wrap_content"
-
android:text="@string/pause">
-
</RadioButton>
-
<RadioButton
-
android:layout_width="wrap_content"
-
android:id="@+id/radio3"
-
android:layout_height="wrap_content"
-
android:text="@string/stop">
-
</RadioButton>
-
</RadioGroup>
-
<TextView
-
android:id="@+id/radioText"
-
android:layout_width="wrap_content"
-
android:layout_height="wrap_content"
-
android:gravity="center">
-
</TextView>
-
</LinearLayout>
既然使用到了AIDL当然要创建AIDL文件了,AIDL文件命名为IremoteService.aidl
- package com.test;
- interface IremoteService{
- String getTime();
- void stop();
- }
下面是界面的代码,在里面同样通过一个线程发消息给主线程,实时更新显示的内容,这次显示的内容为系统时间,由Service端负责获取时间,文件命名为remoteStart.java
- package com.test;
- import android.app.Activity;
- import android.content.ComponentName;
- import android.content.Context;
- import android.content.Intent;
- import android.content.ServiceConnection;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.IBinder;
- import android.os.Message;
- import android.os.RemoteException;
- import android.util.Log;
- import android.widget.RadioButton;
- import android.widget.RadioGroup;
- import android.widget.TextView;
- import android.widget.Toast;
- public class remoteStart extends Activity {
- private String TAG="remoteStart";
- private RadioGroup radiogroup;
- private RadioButton donothing;
- private RadioButton start;
- private RadioButton pause;
- private RadioButton stop;
- private TextView text;
- private boolean status=true;
- private IremoteService remoteservice;
- private String time;
- private getTimeThread gettimethread;
- public void onCreate(Bundle savedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.remote);
- radiogroup=(RadioGroup)findViewById(R.id.radioGroup1);
- donothing=(RadioButton)findViewById(R.id.radio0);
- start=(RadioButton)findViewById(R.id.radio1);
- pause=(RadioButton)findViewById(R.id.radio2);
- stop=(RadioButton)findViewById(R.id.radio3);
- text=(TextView)findViewById(R.id.radioText);
- //初始化更新时间的线程
- gettimethread=new getTimeThread();
- radiogroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(RadioGroup group, int checkedId) {
- if(start.getId()==checkedId){
- if(!status){
- //如果点击过暂停服务,则重新启动更新时间线程
- gettimethread=new getTimeThread();
- status=true;
- }
- new Thread(gettimethread).start();
- Toast.makeText(getApplicationContext(),"启动服务" , Toast.LENGTH_SHORT).show();
- }
- else if(pause.getId()==checkedId){
- status=false;
- Toast.makeText(getApplicationContext(),"暂停服务" , Toast.LENGTH_SHORT).show();
- }
- else if(stop.getId()==checkedId){
- stopactivity();
- Toast.makeText(getApplicationContext(),"停止服务" , Toast.LENGTH_SHORT).show();
- }
- else{
- Toast.makeText(getApplicationContext(),"啥也不做" , Toast.LENGTH_SHORT).show();
- }
- }
- });
- Log.d(TAG,"connecting");
- Intent intent=new Intent("com.test.remoteService");
- bindService(intent,sc,Context.BIND_AUTO_CREATE);
- }
- /*
- * 该线程负责从服务端获取时间,并更新显示
- */
- class getTimeThread implements Runnable{
- public void run(){
- while(status){
- try {
- time=remoteservice.getTime();
- Log.d(TAG,time);
- } catch (RemoteException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- Message msg=new Message();
- msg.what=1;
- h.sendMessage(msg);
- try {
- //每秒更新一次
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- };
- /*
- * 负责接受信息,并根据信息更新显示的时间
- */
- Handler h=new Handler(){
- public void handleMessage(Message msg){
- Log.d(TAG,"msg is "+msg.toString());
- switch(msg.what){
- case 1:
- //更新显示
- text.setText(time);
- break;
- }
- }
- };
- /*
- * 停止服务,并终止
- */
- public void stopactivity(){
- try {
- status=false;
- this.unbindService(sc);
- remoteservice.stop();
- this.finish();
- } catch (RemoteException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- ServiceConnection sc=new ServiceConnection(){
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- remoteservice=IremoteService.Stub.asInterface(service);
- }
- @Override
- public void onServiceDisconnected(ComponentName name) {
- remoteservice=null;
- }
- };
- }
在服务端,相对来说比较简单只是获取系统的时间而已,类命名为remoteService.java
- package com.test;
- import android.app.Service;
- import android.content.Intent;
- import android.os.IBinder;
- import android.os.RemoteException;
- import android.util.Log;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- public class remoteService extends Service {
- private String TAG="remoteService";
- private String time;
- //设置时间格式
- private SimpleDateFormat format=new SimpleDateFormat( "yyyy MMM d EEE HH:mm:ss");
- private IremoteService.Stub binder=new IremoteService.Stub() {
- @Override
- public String getTime() throws RemoteException {
- Log.d(TAG,"gettime");
- //获取系统时间
- time=format.format((new Date()));
- return time;
- }
- @Override
- public void stop() throws RemoteException {
- Log.d(TAG,"stop");
- stopSelf();
- }
- };
- @Override
- public IBinder onBind(Intent intent) {
- // TODO Auto-generated method stub
- return binder;
- }
- public void onCreate(){
- super.onCreate();
- Log.d(TAG,"oncreate");
- }
- }
现在就可以了,界面如下图所示,显示的时间会每秒更新一次。

此外,系统想要顺利运行似乎还缺了几个文件,分别为value目录下的strings.xml和color.xml,下面是strings.xml。
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <string name="hello">请选择</string>
- <string name="app_name">Service练习</string>
- <string name="dirct_start">直接启动service</string>
- <string name="bind_start">bind启动service</string>
- <string name="remote_start">远程启动service</string>
- <string name="do_nothing">啥也不做</string>
- <string name="start">启动服务</string>
- <string name="pause">暂停服务</string>
- <string name="stop">停止服务</string>
- <string-array name="actions">
- <item>啥也不做</item>
- <item>启动服务</item>
- <item>暂停服务</item>
- <item>停止服务</item>
-
- </string-array>
- <string name="select">选择一个操作</string>
- </resources>
下面为color.xml
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <color name="bachgroud">#7fffffff</color>
- <color name="textback">#77777777</color>
- </resources>
至此,我这个系统终于大功告成了。
|
|