Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1536111
  • 博文数量: 113
  • 博客积分: 3526
  • 博客等级: 中校
  • 技术积分: 1815
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-08 09:46
个人简介

记录总结自己的工作

文章分类

全部博文(113)

文章存档

2015年(19)

2014年(10)

2013年(6)

2012年(16)

2011年(24)

2010年(21)

2009年(17)

分类: 嵌入式

2011-03-11 13:45:57

   继续接上文。点击主界面上的“bind启动Service”后,进入第二个副界面。第二个副界面我使用ListView来实现和用户的交互,并且能实时获取服务中提供的数值将其显示在界面上。该界面的布局文件为bind.xml其内容如下:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout
  3.   xmlns:android=""
  4.   android:layout_width="fill_parent"
  5.   android:layout_height="fill_parent">
  6.   <RelativeLayout android:id="@+id/RelativeLayout02"
  7.      android:paddingTop="21.0px"
  8.      android:paddingBottom="10.0px"
  9.      android:layout_width="fill_parent"
  10.      android:layout_height="wrap_content"
  11.      android:layout_marginLeft="15.0px"
  12.      android:layout_marginTop="62.0px"
  13.      android:layout_marginRight="15.0px">
  14.      <ListView android:id="@+id/listView1"
  15.         android:layout_height="wrap_content"
  16.         android:layout_width="fill_parent">
  17.      </ListView>
  18.      <TextView android:id="@+id/bindtext"
  19.         android:layout_width="fill_parent"
  20.         android:layout_height="wrap_content"
  21.         android:layout_below="@+id/listView1"
  22.         android:gravity="center"
  23.      />
  24.   </RelativeLayout>
  25. </LinearLayout>
           在这里我使用了RelativeLayout布局,因为如果还用LinerLayout布局的话就不能正常显示TextView了。界面的类我命名为bindStart.java,在这里碰到了难题,就是如何更新显示的内容。我的想法就是使用一个线程,每一秒中从Service那里获取数字并显示出来。但是系统却频频报错。向别人提问后才知道对于Activity界面的更新只有主线程才可以,别的线程一律不允许碰。那么要告诉主线程更新显示怎么办呢?这就要用到Handler类,Handler类可以说是用来实现线程间的通信。通过一个线程获取数据并发信息给主线程,主线程收到信息后按要求更新显示的内容。类的内容为:

  1. package com.test;

  2. import android.app.Activity;
  3. import android.content.ComponentName;
  4. import android.content.Context;
  5. import android.content.Intent;
  6. import android.content.ServiceConnection;
  7. import android.os.Bundle;
  8. import android.os.Handler;
  9. import android.os.IBinder;
  10. import android.os.Message;
  11. import android.util.Log;
  12. import android.view.View;
  13. import android.widget.AdapterView;
  14. import android.widget.AdapterView.OnItemClickListener;
  15. import android.widget.ArrayAdapter;
  16. import android.widget.ListView;
  17. import android.widget.TextView;
  18. import android.widget.Toast;

  19. public class bindStart extends Activity {
  20.     private final static String TAG="bindStart";
  21.     ListView listView;
  22.     TextView textView;
  23.     ArrayAdapter adapter;
  24.     bindService bindservice;
  25.     int num;
  26.     int act;
  27.     //更新显示用的线程
  28.     fresh freshtext;

  29.     public void onCreate(Bundle savedInstanceState){
  30.         super.onCreate(savedInstanceState);
  31.         setContentView(R.layout.bind);
  32.         listView=(ListView)findViewById(R.id.listView1);
  33.         textView = (TextView)findViewById(R.id.bindtext);
  34.         textView.setText(num+"");
  35.         //设定list的背景色,否则显示不出来
  36.         int mycolor=getResources().getColor(R.color.bachgroud);
  37.         listView.setBackgroundColor(mycolor);
  38.         //获得显示的内容
  39.         adapter=ArrayAdapter.createFromResource(this.getApplicationContext(), R.array.actions,
  40.                 android.R.layout.simple_spinner_dropdown_item);
  41.         listView.setAdapter(adapter);
  42.         freshtext=new fresh();
  43.         //开始bind
  44.         Log.d(TAG, "connecting.....");
  45.         Intent intent = new Intent("com.test.bindService");
  46.         bindService(intent, sc, Context.BIND_AUTO_CREATE);
  47.         //对list添加点击事件响应
  48.         listView.setOnItemClickListener(new OnItemClickListener(){
  49.             @Override
  50.             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  51.                 switch(position){
  52.                     case 0:
  53.                         Toast.makeText(getApplicationContext(), "啥也不做", Toast.LENGTH_SHORT).show();
  54.                         break;
  55.                     case 1:
  56.                         act=1;
  57.                         start(act);
  58.                         Toast.makeText(getApplicationContext(), "启动服务", Toast.LENGTH_SHORT).show();
  59.                         break;
  60.                     case 2:
  61.                         act=2;
  62.                         start(act);
  63.                         Toast.makeText(getApplicationContext(), "暂停服务", Toast.LENGTH_SHORT).show();
  64.                         break;
  65.                     case 3:
  66.                         act=3;
  67.                         start(act);
  68.                         stop();
  69.                         break;
  70.                 }
  71.             }
  72.         });
  73.     }

  74.     private void start(int act) {
  75.        Intent intent=new Intent("com.test.bindService");
  76.        Bundle bundle=new Bundle();
  77.        bundle.putInt("act", act);
  78.        intent.putExtras(bundle);
  79.        startService(intent);
  80.        Log.v("start","startbindservice");
  81.        //如果当前有更新线程在运行,首先结束它
  82.        if(freshtext.running){
  83.            freshtext.running=false;
  84.        }
  85.        //重新启动更新线程
  86.        freshtext=new fresh();
  87.        freshtext.running=true;
  88.        new Thread(freshtext).start();
  89.     }
  90.     public void stop() {
  91.         if(freshtext.running){
  92.             freshtext.running=false;
  93.         }
  94.         this.unbindService(sc);
  95.         this.finish();
  96.     }

  97.     class fresh implements Runnable{
  98.         Boolean running=false;
  99.         @Override
  100.         public void run() {
  101.             while(running){
  102.                 try {
  103.                     Thread.sleep(1000);
  104.                 } catch (InterruptedException e) {
  105.                     e.printStackTrace();
  106.                 }
  107.                 //获取服务中产生的数字
  108.                 num =bindservice.get();
  109.                 //通过handler发消息给主线程,更新显示的内容
  110.                 Message msg=new Message();
  111.                 msg.what=1;
  112.                 h.sendMessage(msg);
  113.                 Log.d(TAG,"num is :"+num);
  114.             }

  115.         }

  116.     }

  117.     ServiceConnection sc=new ServiceConnection(){
  118.         @Override
  119.         public void onServiceConnected(ComponentName name, IBinder service) {
  120.             bindservice=((bindService.myBinder)service).getService();
  121.             Log.d(TAG, "in onServiceConnected");
  122.         }
  123.         @Override
  124.         public void onServiceDisconnected(ComponentName name) {
  125.             bindservice=null;
  126.         }

  127.     };
  128.    /*
  129.     * 主线程处理收到的信息
  130.     */
  131.     Handler h=new Handler(){
  132.         public void handleMessage(Message msg){
  133.             Log.d(TAG,"msg is "+msg.toString());
  134.             switch(msg.what){
  135.                 case 1:
  136.                 textView.setText(num+"");
  137.                 break;
  138.             }
  139.         }
  140.     };
  141.    }
      接下来当然是服务类了,没有什么特别之处,还是每秒钟对变量加一。

  1. package com.test;

  2. import android.app.Service;
  3. import android.content.Intent;
  4. import android.os.Binder;
  5. import android.os.Bundle;
  6. import android.os.IBinder;
  7. import android.util.Log;

  8. public class bindService extends Service {

  9.     private final static String TAG="bindService";
  10.     private IBinder binder=new myBinder();
  11.     private int n=0;
  12.     private count thread;
  13.     @Override
  14.     public IBinder onBind(Intent intent) {
  15.         // TODO Auto-generated method stub
  16.         return binder;
  17.     }

  18.     public class myBinder extends Binder{

  19.         public bindService getService(){
  20.             return bindService.this;
  21.         }
  22.     }

  23.     public int get(){
  24.         return n;
  25.     }

  26.     public void onCreate(){
  27.         super.onCreate();
  28.         Log.d(TAG,"onCreate");
  29.         thread=new count();
  30.     }

  31.     public void onStart(Intent intent, int startId){
  32.         Log.d(TAG,"onstart");
  33.         if(intent!=null){
  34.             Bundle budle=intent.getExtras();
  35.             int act=budle.getInt("act");
  36.             switch(act){
  37.                 case 1:
  38.                     start();
  39.                     break;
  40.                 case 2:
  41.                     stop();
  42.                     break;
  43.                  case 3:
                        finsish();

                }
            }
        }

        private void finsish() {
            thread.setPause(true);
            stopSelf();

        }

  44.     class count extends Thread{
  45.         private boolean pause=false;
  46.         public void setPause(boolean tof){
  47.             pause=tof;
  48.         }
  49.         public boolean getPauseStatues(){
  50.             return pause;
  51.         }

  52.         public void run(){
  53.             while(!pause){
  54.                 try {
  55.                     Thread.sleep(1000);
  56.                 } catch (InterruptedException e) {
  57.                     e.printStackTrace();
  58.                 }
  59.                 n++;
  60.                 Log.d(TAG,"n is:"+n);
  61.             }
  62.         }
  63.     }

  64.     private void stop() {
  65.         thread.setPause(true);
  66.     }

  67.     private void start() {
  68.         stop();
  69.       if(thread.getPauseStatues()==true){
  70.           thread=new count();
  71.           thread.setPause(false);
  72.       }
  73.        thread.start();
  74.        Log.d(TAG,String.valueOf(thread.getPauseStatues()));
  75.     }
  76. }
        该界面的显示如下图所示:最下面的数字每秒钟会更新一次。



       最后就是远程Service了,使用了AIDL接口实现Activity和Service之间的通信,在这个界面中我使用单选按钮来和用户就行交互。布局文件为remote.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout
  3.   xmlns:android=""
  4.   android:orientation="vertical"
  5.   android:layout_width="fill_parent"
  6.   android:layout_height="fill_parent">
  7.     <RadioGroup
  8.         android:id="@+id/radioGroup1"
  9.         android:layout_width="wrap_content"
  10.         android:layout_height="wrap_content"
  11.         android:gravity="center">
  12.         <RadioButton
  13.              android:layout_width="wrap_content"
  14.              android:id="@+id/radio0"
  15.              android:layout_height="wrap_content"
  16.              android:text="@string/do_nothing"
  17.              android:checked="true">
  18.         </RadioButton>
  19.         <RadioButton
  20.             android:layout_width="wrap_content"
  21.             android:id="@+id/radio1"
  22.             android:layout_height="wrap_content"
  23.             android:text="@string/start">
  24.         </RadioButton>
  25.         <RadioButton
  26.             android:layout_width="wrap_content"
  27.             android:id="@+id/radio2"
  28.             android:layout_height="wrap_content"
  29.             android:text="@string/pause">
  30.         </RadioButton>
  31.         <RadioButton
  32.             android:layout_width="wrap_content"
  33.             android:id="@+id/radio3"
  34.             android:layout_height="wrap_content"
  35.             android:text="@string/stop">
  36.         </RadioButton>
  37.     </RadioGroup>
  38.     <TextView
  39.         android:id="@+id/radioText"
  40.         android:layout_width="wrap_content"
  41.         android:layout_height="wrap_content"
  42.         android:gravity="center">
  43.     </TextView>
  44. </LinearLayout>


        既然使用到了AIDL当然要创建AIDL文件了,AIDL文件命名为IremoteService.aidl
  1. package com.test;
  2. interface IremoteService{
  3. String getTime();

  4. void stop();
  5. }
      下面是界面的代码,在里面同样通过一个线程发消息给主线程,实时更新显示的内容,这次显示的内容为系统时间,由Service端负责获取时间,文件命名为remoteStart.java
  1. package com.test;

  2. import android.app.Activity;
  3. import android.content.ComponentName;
  4. import android.content.Context;
  5. import android.content.Intent;
  6. import android.content.ServiceConnection;
  7. import android.os.Bundle;
  8. import android.os.Handler;
  9. import android.os.IBinder;
  10. import android.os.Message;
  11. import android.os.RemoteException;
  12. import android.util.Log;
  13. import android.widget.RadioButton;
  14. import android.widget.RadioGroup;
  15. import android.widget.TextView;
  16. import android.widget.Toast;

  17. public class remoteStart extends Activity {
  18.     private String TAG="remoteStart";
  19.     private RadioGroup radiogroup;
  20.     private RadioButton donothing;
  21.     private RadioButton start;
  22.     private RadioButton pause;
  23.     private RadioButton stop;
  24.     private TextView text;
  25.     private boolean status=true;
  26.     private IremoteService remoteservice;
  27.     private String time;
  28.     private getTimeThread gettimethread;

  29.     public void onCreate(Bundle savedInstanceState){
  30.         super.onCreate(savedInstanceState);
  31.         setContentView(R.layout.remote);
  32.         radiogroup=(RadioGroup)findViewById(R.id.radioGroup1);
  33.         donothing=(RadioButton)findViewById(R.id.radio0);
  34.         start=(RadioButton)findViewById(R.id.radio1);
  35.         pause=(RadioButton)findViewById(R.id.radio2);
  36.         stop=(RadioButton)findViewById(R.id.radio3);
  37.         text=(TextView)findViewById(R.id.radioText);
  38.         //初始化更新时间的线程
  39.         gettimethread=new getTimeThread();
  40.         radiogroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {

  41.             @Override
  42.             public void onCheckedChanged(RadioGroup group, int checkedId) {
  43.                 if(start.getId()==checkedId){
  44.                     if(!status){
  45.                         //如果点击过暂停服务,则重新启动更新时间线程
  46.                         gettimethread=new getTimeThread();
  47.                         status=true;
  48.                     }
  49.                     new Thread(gettimethread).start();
  50.                     Toast.makeText(getApplicationContext(),"启动服务" , Toast.LENGTH_SHORT).show();
  51.                 }
  52.                 else if(pause.getId()==checkedId){
  53.                     status=false;
  54.                     Toast.makeText(getApplicationContext(),"暂停服务" , Toast.LENGTH_SHORT).show();
  55.                 }
  56.                 else if(stop.getId()==checkedId){
  57.                   stopactivity();

  58.                     Toast.makeText(getApplicationContext(),"停止服务" , Toast.LENGTH_SHORT).show();
  59.                 }
  60.                 else{
  61.                     Toast.makeText(getApplicationContext(),"啥也不做" , Toast.LENGTH_SHORT).show();
  62.                 }
  63.             }
  64.         });

  65.         Log.d(TAG,"connecting");
  66.         Intent intent=new Intent("com.test.remoteService");
  67.         bindService(intent,sc,Context.BIND_AUTO_CREATE);

  68.     }

  69.     /*
  70.      * 该线程负责从服务端获取时间,并更新显示
  71.      */
  72.    class getTimeThread implements Runnable{
  73.         public void run(){
  74.             while(status){
  75.                 try {
  76.                     time=remoteservice.getTime();
  77.                     Log.d(TAG,time);
  78.                 } catch (RemoteException e) {
  79.                     // TODO Auto-generated catch block
  80.                     e.printStackTrace();
  81.                 }
  82.                 Message msg=new Message();
  83.                 msg.what=1;
  84.                 h.sendMessage(msg);
  85.                 try {
  86.                     //每秒更新一次
  87.                     Thread.sleep(1000);
  88.                 } catch (InterruptedException e) {
  89.                     // TODO Auto-generated catch block
  90.                     e.printStackTrace();
  91.                 }
  92.             }
  93.         }
  94.     };
  95.     /*
  96.      * 负责接受信息,并根据信息更新显示的时间
  97.      */
  98.     Handler h=new Handler(){
  99.         public void handleMessage(Message msg){
  100.             Log.d(TAG,"msg is "+msg.toString());
  101.             switch(msg.what){
  102.                 case 1:
  103.                 //更新显示
  104.                 text.setText(time);
  105.                 break;
  106.             }
  107.         }
  108.     };
  109.     /*
  110.      * 停止服务,并终止
  111.      */
  112.     public void stopactivity(){
  113.         try {
  114.             status=false;
  115.             this.unbindService(sc);
  116.             remoteservice.stop();
  117.             this.finish();
  118.         } catch (RemoteException e) {
  119.             // TODO Auto-generated catch block
  120.             e.printStackTrace();
  121.         }
  122.     }

  123.     ServiceConnection sc=new ServiceConnection(){
  124.         @Override
  125.         public void onServiceConnected(ComponentName name, IBinder service) {
  126.             remoteservice=IremoteService.Stub.asInterface(service);
  127.         }
  128.         @Override
  129.         public void onServiceDisconnected(ComponentName name) {
  130.             remoteservice=null;
  131.         }
  132.     };
  133. }
      在服务端,相对来说比较简单只是获取系统的时间而已,类命名为remoteService.java
  1. package com.test;

  2. import android.app.Service;
  3. import android.content.Intent;
  4. import android.os.IBinder;
  5. import android.os.RemoteException;
  6. import android.util.Log;

  7. import java.text.SimpleDateFormat;
  8. import java.util.Date;

  9. public class remoteService extends Service {
  10.     private String TAG="remoteService";
  11.     private String time;
  12.     //设置时间格式
  13.     private SimpleDateFormat format=new SimpleDateFormat( "yyyy MMM d EEE HH:mm:ss");
  14.     private IremoteService.Stub binder=new IremoteService.Stub() {

  15.         @Override
  16.         public String getTime() throws RemoteException {
  17.             Log.d(TAG,"gettime");
  18.             //获取系统时间
  19.             time=format.format((new Date()));
  20.             return time;
  21.         }

  22.         @Override
  23.         public void stop() throws RemoteException {
  24.             Log.d(TAG,"stop");
  25.             stopSelf();
  26.         }
  27.     };
  28.     @Override
  29.     public IBinder onBind(Intent intent) {
  30.         // TODO Auto-generated method stub
  31.         return binder;
  32.     }

  33.     public void onCreate(){
  34.         super.onCreate();
  35.         Log.d(TAG,"oncreate");
  36.     }
  37. }
        现在就可以了,界面如下图所示,显示的时间会每秒更新一次。



    此外,系统想要顺利运行似乎还缺了几个文件,分别为value目录下的strings.xml和color.xml,下面是strings.xml。
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3.     <string name="hello">请选择</string>
  4.     <string name="app_name">Service练习</string>
  5.     <string name="dirct_start">直接启动service</string>
  6.     <string name="bind_start">bind启动service</string>
  7.     <string name="remote_start">远程启动service</string>
  8.     <string name="do_nothing">啥也不做</string>
  9.     <string name="start">启动服务</string>
  10.     <string name="pause">暂停服务</string>
  11.     <string name="stop">停止服务</string>
  12.     <string-array name="actions">
  13.     <item>啥也不做</item>
  14.     <item>启动服务</item>
  15.     <item>暂停服务</item>
  16.     <item>停止服务</item>
  17.     
  18.      </string-array>
  19.      <string name="select">选择一个操作</string>
  20. </resources>
      下面为color.xml
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3. <color name="bachgroud">#7fffffff</color>
  4. <color name="textback">#77777777</color>
  5. </resources>
     至此,我这个系统终于大功告成了。
阅读(5285) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~