service 总结

来源:互联网 发布:办公软件培训课件 编辑:程序博客网 时间:2024/06/05 19:29

最近一直在学习service ,刚开始的时候以为service跟activity一样,很简单,

但后来学习中发现里面好多东西自己都看不懂,真是不知道该从哪里开始做起了

现在好好理一下:

首先在做关于service的简单实用时摘抄了别人的一个例子,里面,没有牵涉到 bind绑定

但下一个如果要绑定activity的话继承service的类就要继承一个接口,还要实现一个内部类且该类也要继承该接口

这是为什么呢!我没有实现接口的定义 ServiceConnection这个接口两个函数当建立连接时别调用,当失去连接时被调用!它有什么作用,我每次失败时该函数都不被调用,用startservice就可以,用bindservice就出错!

那把serviceconnection里面的内容给注释掉,成功运行,

结合dmms 说明 service2 s2 = ((service2.MyBinder)service).getService();出错切实类型强制转换出错 应该是内部类myBinder出错它又继承了Binder类,关键是这个内部类是用来干什么的?我们看一下 Binder这个类!他其实就是两个进程数据的中转站,这里也就是activity与service的中转站(客户端和服务器)。他把activity请求的东西转给service后。。。。。当然内部太复杂,不想管了,上面那就代码应该是想通过继承Binder来返回从service获得的信息。但中间cast出错!反正这个程序没有用到返回的数据,我先不管了!

看一下别人关于service的总结的程序

 

学习android有一段时间了,感觉学到的东西似乎很有限,归根结底就是自己动手写的程序太少了。我觉得学习编程,光停留在“看“是不行了,看了10成感觉似乎也就能记得一两成,等碰到问题的时候又要回去查看。所以必须通过动手来学习,在动手的过程中会碰到很多看的时候根本不会发现的问题,带着问题去看去解决问题才会得到很大的提高。在我做这个练习的过程中碰到多很多问题,我会在下面对应的位置将问题给总结上。
     首先说一下程序的主要结构。有一个主界面Activity,通过主界面可以打开三个副界面Activity,每个副界面对应一个Service类,代表了一种使用Service的方法,其具体包括:
      1.简单的启动Service;
      2.通过bind使用Service;
      3.使用AIDL实现进程间的通信。

     先看一下Manifest.xml文件吧。在这里面声明了3个Activity和3个Service。在这里遇到的问题主要是出来的界面左右各空了一块,没有占据整个屏幕。查找原因是少了最后的那句 <uses-sdk android:minSdkVersion="7"/>,其原因估计默认的版本比较小,不能很好地适应我的模拟器。

<?xml version="1.0"encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.test"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".start" android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity android:name=".dirstart">
        </activity>
        <activity android:name=".bindStart">
        </activity>
        <activity android:name=".remoteStart">
        </activity>
        <service android:enabled="true" android:name=".dirtStartService">
            <intent-filter>
                <action android:name="com.test.dirStartService"></action>
            </intent-filter>
        </service>
        <service android:enabled="true" android:name=".bindService">
            <intent-filter>
                <action android:name="com.test.bindService"></action>
            </intent-filter>
        </service>
         <service android:enabled="true" android:name=".remoteService">
            <intent-filter>
                <action android:name="com.test.remoteService"></action>
            </intent-filter>
        </service>
    </application>
    <uses-sdk android:minSdkVersion="7"/>
</manifest>

     下面是主界面的代码,我将其命名为start.java。这里没有什么特别之处,只是在一个Activiy中添加了3个按钮,为每个按钮都添加了事件响应行为,启动各个副界面。

package com.test;


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

publicclassstartextendsActivityimplements OnClickListener{
    privateString TAG="servicetest";
    privateButton dirtstart;
    privateButton bindstart;
    privateButton remotestart;
    /** Called when the activity is first created. */
    @Override
    publicvoid onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        dirtstart=(Button)findViewById(R.id.dirtstart);
        bindstart=(Button)findViewById(R.id.bindstart);
        remotestart=(Button)findViewById(R.id.remtstart);
        addListener();
    }
    /*
     * 添加对按钮的监听
     */
    privatevoid addListener(){
        dirtstart.setOnClickListener(this);
        bindstart.setOnClickListener(this);
        remotestart.setOnClickListener(this);
    }
    @Override
    publicvoid onClick(View v){
       switch(v.getId()){
           //以直接启动的方式启动服务
           case R.id.dirtstart:
               Toast.makeText(this.getApplicationContext(),"dirstart", Toast.LENGTH_SHORT).show();
               Log.d(TAG,"dirstart");
               Intent intent=new Intent(this,dirstart.class);
               startActivity(intent);
               break;
           //以bind的方式启动服务,并同服务进行交互
           case R.id.bindstart:
               Toast.makeText(this.getApplicationContext(),"bindstart", Toast.LENGTH_SHORT).show();
               Log.d(TAG,"bindstart");
               Intent intent1=new Intent(this,bindStart.class);
               startActivity(intent1);
               break;
           //以AIDL实现进程间的通信
           case R.id.remtstart:
               Toast.makeText(getApplicationContext(),"remtstart", Toast.LENGTH_SHORT).show();
               Log.d(TAG,"remotestart");               Intent intent2=new Intent(this,remoteStart.class);
               startActivity(intent2);
               break;
       }

    }
}

   主界面的显示如下图所示:


    下面说一下各个副界面的实现。


    在点击了“直接启动Service”按钮后,触发事件启动第一个副界面,该界面使用的布局文件为/layout/dir.xml,如下所以。可以看到在这里我们不单纯地使用按钮了,而是使用了下拉菜单的形式,具体的实现我参考了SDK中Spinner的实现。

<?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">
   
  <TextView android:text="直接控制服务"
    android:gravity="center" android:id="@+id/textView1"
    android:layout_width="fill_parent" android:layout_height="wrap_content"></TextView>
<Spinner
    android:id="@+id/spinr"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent"
    android:drawSelectorOnTop ="true"
    android:prompt="@string/select"
    >
    </Spinner>
 <TextView android:id="@+id/textview"
    android:gravity="center"
    android:layout_width="fill_parent" android:layout_height="wrap_content"></TextView>
</LinearLayout>

      对于该界面起名为dirstart.java,代码如下。在这里面使用了一个SpinnerAdapter来装载Spinner所要显示的内容,当然对于内容的定义是在value.xml中进行定义的,这个会在后面贴上。

package com.test;import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TextView;
import android.widget.Toast;

publicclass dirstart extendsActivity{
    SpinnerAdapter mAdapter;
    Spinner spinner;
    TextView textview;

    publicvoid onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.dir);
        textview=(TextView)findViewById(R.id.textview);
        spinner=(Spinner)findViewById(R.id.spinr);
        //获取内容
        this.mAdapter=ArrayAdapter.createFromResource(this.getApplicationContext(), R.array.actions,
                android.R.layout.simple_spinner_dropdown_item);
        //添加spinner所要显示的内容
        spinner.setAdapter(mAdapter);
        //给spinner添加监听器
        OnItemSelectedListener spinnerListener =new myOnItemSelectedListener(this,this.mAdapter);
        spinner.setOnItemSelectedListener(spinnerListener);

    }
    //停止服务并结束本ACTIVITY
    publicvoidstop(){
        Intent intent=new Intent("com.test.dirStartService");
        stopService(intent);
        this.finish();
    }

    class myOnItemSelectedListener implements OnItemSelectedListener{
        public myOnItemSelectedListener(dirstart dirstart, SpinnerAdapter mAdapter){
            // TODO Auto-generated constructor stub
        }

        @Override
        publicvoid onItemSelected(AdapterView<?>parent,Viewview,intposition,longid){
            int act=0;
            switch(Integer.parseInt(String.valueOf((id)))){
                case 0:
                    textview.setText("啥也不做");
                   // Toast.makeText(getApplicationContext(), "啥也不做", Toast.LENGTH_LONG).show();
                    break;
                case 1:
                    act=1;
                    textview.setText("服务已启动");
                  // Toast.makeText(getApplicationContext(), "启动服务", Toast.LENGTH_LONG).show();
                    start(act);
                    break;
                case 2:
                    act=2;
                    textview.setText("服务已结束");
                  // Toast.makeText(getApplicationContext(), "结束服务", Toast.LENGTH_LONG).show();
                    start(act);
                    break;
                case 3:
                    stop();
                    break;
            }

        }
        /*
         * 启动服务
         */
        privatevoidstart(int act){
            Intent intent=new Intent("com.test.dirStartService");
            Bundle bundle=new Bundle();
            //给要启动的服务传递参数
            bundle.putInt("act", act);
            intent.putExtras(bundle);
            Log.v("start","startservice");
            startService(intent);
        }

        @Override
        publicvoid onNothingSelected(AdapterView<?>parent){
            // TODO Auto-generated method stub

        }

    }
}

      可以看到上面只是一个Activty,只是同用户交互的窗口,服务的实现还要在另外的一个类dirStartService.java中实现。下面是服务的代码。在服务的代码中,通过一个线程来操作一个变量,每一秒钟使变量的值加一,并在logcat中打印出来。这里碰到的问题就是线程的启动方面,因为在程序中只使用了一个线程,如果服务在暂停后又开启服务的话就会发生错误,因为前面的线程已经执行完了。所以在每次启动线程前要判断线程的状态,如果前面有线程执行过,就需要重新建立一下线程的对象。

package com.test;

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

publicclass dirtStartService extends Service {
    privatestaticfinalString TAG="dirService";
    privateint n=0;
    //用来计数的线程
    privatecountthread;

    @Override
    public IBinder onBind(Intent intent){
        returnnull;
    }

    publicvoid onCreate(){
        super.onCreate();
        Log.d(TAG,"oncreate");
        thread=newcount();
    }
    publicvoid onStart(Intent intent,int startId){
        Log.d(TAG,"onstart");
        if(intent!=null){
            //获取传送来的参数,并根据参数进行对应的操作
            Bundle bundle=intent.getExtras();
            int act=bundle.getInt("act");
            Log.d(TAG,"act is:"+act);
            switch(act){
                case 1:
                    start();
                    break;
                case 2:
                    stop();
                    break;
            }
        }
    }
    /*
     * 线程类
     */
    classcountextendsThread{
        //控制线程的结束
        privateboolean pause=false;
        publicvoid setPause(boolean tof){
            pause=tof;
        }
        publicboolean getPauseStatues(){
            return pause;
        }

        publicvoidrun(){
            while(!pause){
                try{
                    Thread.sleep(1000);
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
                //每隔一秒钟输出加一后的值
                n++;
                Log.d(TAG,"n is:"+n);
            }
        }
    }
    /*
     * 结束线程的执行
     */
    privatevoidstop(){
        thread.setPause(true);
    }
    /*
     * 重新启动线程
     */
    privatevoidstart(){
      //如果前面有线程在执行,则重新启动线程
      if(thread.getPauseStatues()==true){
          thread=newcount();
          thread.setPause(false);
      }
       thread.start();
       Log.d(TAG,String.valueOf(thread.getPauseStatues()));
    }
}

        该界面的效果如下图所示:


 
       当点击该Spinner后,弹出提前设定好的选项,单击某一项进行操作。



     启动服务后的输出结果如下图所示:


        将所有的东西都放在一篇文章中显得太多,下篇文章介绍另外两种方式的实现。

  继续接上文。点击主界面上的“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;

publicclass bindStart extendsActivity{
    privatefinalstaticString TAG="bindStart";
    ListViewlistView;
    TextView textView;
    ArrayAdapter adapter;
    bindService bindservice;
    int num;
    int act;
    //更新显示用的线程
    fresh freshtext;

    publicvoid 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
            publicvoid onItemClick(AdapterView<?>parent,Viewview,intposition,longid){
                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;
                }
            }
        });
    }

    privatevoidstart(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;
       newThread(freshtext).start();
    }
    publicvoidstop(){
        if(freshtext.running){
            freshtext.running=false;
        }
        this.unbindService(sc);
        this.finish();
    }

    class fresh implementsRunnable{
        Boolean running=false;
        @Override
        publicvoidrun(){
            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
        publicvoid onServiceConnected(ComponentName name, IBinder service){
            bindservice=((bindService.myBinder)service).getService();
            Log.d(TAG,"in onServiceConnected");
        }
        @Override
        publicvoid onServiceDisconnected(ComponentName name){
            bindservice=null;
        }

    };
   /*
    * 主线程处理收到的信息
    */
    Handler h=newHandler(){
        publicvoid 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;

publicclass bindService extends Service {

    privatefinalstaticString TAG="bindService";
    private IBinder binder=new myBinder();
    privateint n=0;
    privatecountthread;
    @Override
    public IBinder onBind(Intent intent){
        // TODO Auto-generated method stub
        return binder;
    }

    publicclass myBinder extends Binder{

        public bindService getService(){
            return bindService.this;
        }
    }

    publicintget(){
        return n;
    }

    publicvoid onCreate(){
        super.onCreate();
        Log.d(TAG,"onCreate");
        thread=newcount();
    }

    publicvoid 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();

    }

    classcountextendsThread{
        privateboolean pause=false;
        publicvoid setPause(boolean tof){
            pause=tof;
        }
        publicboolean getPauseStatues(){
            return pause;
        }

        publicvoidrun(){
            while(!pause){
                try{
                    Thread.sleep(1000);
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
                n++;
                Log.d(TAG,"n is:"+n);
            }
        }
    }

    privatevoidstop(){
        thread.setPause(true);
    }

    privatevoidstart(){
        stop();
      if(thread.getPauseStatues()==true){
          thread=newcount();
          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;

publicclass remoteStart extendsActivity{
    privateString TAG="remoteStart";
    private RadioGroup radiogroup;
    private RadioButton donothing;
    private RadioButton start;
    private RadioButton pause;
    private RadioButton stop;
    private TextView text;
    privatebooleanstatus=true;
    private IremoteService remoteservice;
    privateStringtime;
    private getTimeThread gettimethread;

    publicvoid 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
            publicvoid onCheckedChanged(RadioGroup group,int checkedId){
                if(start.getId()==checkedId){
                    if(!status){
                        //如果点击过暂停服务,则重新启动更新时间线程
                        gettimethread=new getTimeThread();
                        status=true;
                    }
                    newThread(gettimethread).start();
                    Toast.makeText(getApplicationContext(),"启动服务", Toast.LENGTH_SHORT).show();
                }
                elseif(pause.getId()==checkedId){
                    status=false;
                    Toast.makeText(getApplicationContext(),"暂停服务", Toast.LENGTH_SHORT).show();
                }
                elseif(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 implementsRunnable{
        publicvoidrun(){
            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=newHandler(){
        publicvoid handleMessage(Message msg){
            Log.d(TAG,"msg is "+msg.toString());
            switch(msg.what){
                case 1:
                //更新显示
                text.setText(time);
                break;
            }
        }
    };
    /*
     * 停止服务,并终止
     */
    publicvoid 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
        publicvoid onServiceConnected(ComponentName name, IBinder service){
            remoteservice=IremoteService.Stub.asInterface(service);
        }
        @Override
        publicvoid 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;

importjava.text.SimpleDateFormat;
importjava.util.Date;

publicclass remoteService extends Service {
    privateString TAG="remoteService";
    privateStringtime;
    //设置时间格式
    privateSimpleDateFormatformat=newSimpleDateFormat("yyyy MMM d EEE HH:mm:ss");
    private IremoteService.Stub binder=new IremoteService.Stub(){

        @Override
        publicStringgetTime()throwsRemoteException{
            Log.d(TAG,"gettime");
            //获取系统时间
            time=format.format((newDate()));
            returntime;
        }

        @Override
        publicvoidstop()throwsRemoteException{
            Log.d(TAG,"stop");
            stopSelf();
        }
    };
    @Override
    public IBinder onBind(Intent intent){
        // TODO Auto-generated method stub
        return binder;
    }

    publicvoid 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>

     至此,我这个系统终于大功告成了。