Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1571236
  • 博文数量: 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-10 15:00:48

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

     先看一下Manifest.xml文件吧。在这里面声明了3个Activity和3个Service。在这里遇到的问题主要是出来的界面左右各空了一块,没有占据整个屏幕。查找原因是少了最后的那句
<uses-sdk android:minSdkVersion="7"/>,其原因估计默认的版本比较小,不能很好地适应我的模拟器。
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android=""
  3.       package="com.test"
  4.       android:versionCode="1"
  5.       android:versionName="1.0">
  6.     <application android:icon="@drawable/icon" android:label="@string/app_name">
  7.         <activity android:name=".start" android:label="@string/app_name">
  8.             <intent-filter>
  9.                 <action android:name="android.intent.action.MAIN" />
  10.                 <category android:name="android.intent.category.LAUNCHER" />
  11.             </intent-filter>
  12.         </activity>
  13.         <activity android:name=".dirstart">
  14.         </activity>
  15.         <activity android:name=".bindStart">
  16.         </activity>
  17.         <activity android:name=".remoteStart">
  18.         </activity>
  19.         <service android:enabled="true" android:name=".dirtStartService">
  20.             <intent-filter>
  21.                 <action android:name="com.test.dirStartService"></action>
  22.             </intent-filter>
  23.         </service>
  24.         <service android:enabled="true" android:name=".bindService">
  25.             <intent-filter>
  26.                 <action android:name="com.test.bindService"></action>
  27.             </intent-filter>
  28.         </service>
  29.          <service android:enabled="true" android:name=".remoteService">
  30.             <intent-filter>
  31.                 <action android:name="com.test.remoteService"></action>
  32.             </intent-filter>
  33.         </service>
  34.     </application>
  35.     <uses-sdk android:minSdkVersion="7" />
  36. </manifest>
     下面是主界面的代码,我将其命名为start.java。这里没有什么特别之处,只是在一个Activiy中添加了3个按钮,为每个按钮都添加了事件响应行为,启动各个副界面。
  1. package com.test;


  2. import android.app.Activity;
  3. import android.content.Intent;
  4. import android.os.Bundle;
  5. import android.util.Log;
  6. import android.view.View;
  7. import android.view.View.OnClickListener;
  8. import android.widget.Button;
  9. import android.widget.Toast;

  10. public class start extends Activity implements OnClickListener{
  11.     private String TAG="servicetest";
  12.     private Button dirtstart;
  13.     private Button bindstart;
  14.     private Button remotestart;
  15.     /** Called when the activity is first created. */
  16.     @Override
  17.     public void onCreate(Bundle savedInstanceState) {
  18.         super.onCreate(savedInstanceState);
  19.         setContentView(R.layout.main);
  20.         dirtstart=(Button)findViewById(R.id.dirtstart);
  21.         bindstart=(Button)findViewById(R.id.bindstart);
  22.         remotestart=(Button)findViewById(R.id.remtstart);
  23.         addListener();
  24.     }
  25.     /*
  26.      * 添加对按钮的监听
  27.      */
  28.     private void addListener() {
  29.         dirtstart.setOnClickListener(this);
  30.         bindstart.setOnClickListener(this);
  31.         remotestart.setOnClickListener(this);
  32.     }
  33.     @Override
  34.     public void onClick(View v) {
  35.        switch(v.getId()){
  36.            //以直接启动的方式启动服务
  37.            case R.id.dirtstart:
  38.                Toast.makeText(this.getApplicationContext(), "dirstart", Toast.LENGTH_SHORT).show();
  39.                Log.d(TAG,"dirstart");
  40.                Intent intent=new Intent(this,dirstart.class);
  41.                startActivity(intent);
  42.                break;
  43.            //以bind的方式启动服务,并同服务进行交互
  44.            case R.id.bindstart:
  45.                Toast.makeText(this.getApplicationContext() , "bindstart", Toast.LENGTH_SHORT).show();
  46.                Log.d(TAG,"bindstart");
  47.                Intent intent1=new Intent(this,bindStart.class);
  48.                startActivity(intent1);
  49.                break;
  50.            //以AIDL实现进程间的通信
  51.            case R.id.remtstart:
  52.                Toast.makeText(getApplicationContext(), "remtstart", Toast.LENGTH_SHORT).show();
  53.                Log.d(TAG,"remotestart");
  54.                Intent intent2=new Intent(this,remoteStart.class);
                   startActivity(intent2);
  55.                break;
  56.        }

  57.     }
  58. }
   主界面的显示如下图所示:


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


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

  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.    
  8.   <TextView android:text="直接控制服务"
  9.     android:gravity="center" android:id="@+id/textView1"
  10.     android:layout_width="fill_parent" android:layout_height="wrap_content"></TextView>
  11. <Spinner
  12.     android:id="@+id/spinr"
  13.     android:layout_height="wrap_content"
  14.     android:layout_width="fill_parent"
  15.     android:drawSelectorOnTop = "true"
  16.     android:prompt="@string/select"
  17.     >
  18.     </Spinner>
  19.  <TextView android:id="@+id/textview"
  20.     android:gravity="center"
  21.     android:layout_width="fill_parent" android:layout_height="wrap_content"></TextView>
  22. </LinearLayout>
       对于该界面起名为dirstart.java,代码如下。在这里面使用了一个SpinnerAdapter来装载Spinner所要显示的内容,当然对于内容的定义是在value.xml中进行定义的,这个会在后面贴上。
  1. package com.test;
  2. import android.app.Activity;
  3. import android.content.Intent;
  4. import android.os.Bundle;
  5. import android.util.Log;
  6. import android.view.View;
  7. import android.widget.AdapterView;
  8. import android.widget.AdapterView.OnItemSelectedListener;
  9. import android.widget.ArrayAdapter;
  10. import android.widget.Spinner;
  11. import android.widget.SpinnerAdapter;
  12. import android.widget.TextView;
  13. import android.widget.Toast;

  14. public class dirstart extends Activity {
  15.     SpinnerAdapter mAdapter;
  16.     Spinner spinner;
  17.     TextView textview;

  18.     public void onCreate(Bundle savedInstanceState){
  19.         super.onCreate(savedInstanceState);
  20.         setContentView(R.layout.dir);
  21.         textview=(TextView)findViewById(R.id.textview);
  22.         spinner=(Spinner)findViewById(R.id.spinr);
  23.         //获取内容
  24.         this.mAdapter=ArrayAdapter.createFromResource(this.getApplicationContext(), R.array.actions,
  25.                 android.R.layout.simple_spinner_dropdown_item);
  26.         //添加spinner所要显示的内容
  27.         spinner.setAdapter(mAdapter);
  28.         //给spinner添加监听器
  29.         OnItemSelectedListener spinnerListener = new myOnItemSelectedListener(this,this.mAdapter);
  30.         spinner.setOnItemSelectedListener(spinnerListener);

  31.     }
  32.     //停止服务并结束本ACTIVITY
  33.     public void stop() {
  34.         Intent intent=new Intent("com.test.dirStartService");
  35.         stopService(intent);
  36.         this.finish();
  37.     }

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

  42.         @Override
  43.         public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
  44.             int act=0;
  45.             switch(Integer.parseInt(String.valueOf((id)))){
  46.                 case 0:
  47.                     textview.setText("啥也不做");
  48.                    // Toast.makeText(getApplicationContext(), "啥也不做", Toast.LENGTH_LONG).show();
  49.                     break;
  50.                 case 1:
  51.                     act=1;
  52.                     textview.setText("服务已启动");
  53.                   // Toast.makeText(getApplicationContext(), "启动服务", Toast.LENGTH_LONG).show();
  54.                     start(act);
  55.                     break;
  56.                 case 2:
  57.                     act=2;
  58.                     textview.setText("服务已结束");
  59.                   // Toast.makeText(getApplicationContext(), "结束服务", Toast.LENGTH_LONG).show();
  60.                     start(act);
  61.                     break;
  62.                 case 3:
  63.                     stop();
  64.                     break;
  65.             }

  66.         }
  67.         /*
  68.          * 启动服务
  69.          */
  70.         private void start(int act) {
  71.             Intent intent=new Intent("com.test.dirStartService");
  72.             Bundle bundle=new Bundle();
  73.             //给要启动的服务传递参数
  74.             bundle.putInt("act", act);
  75.             intent.putExtras(bundle);
  76.             Log.v("start","startservice");
  77.             startService(intent);
  78.         }

  79.         @Override
  80.         public void onNothingSelected(AdapterView<?> parent) {
  81.             // TODO Auto-generated method stub

  82.         }

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

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

  7. public class dirtStartService extends Service {
  8.     private static final String TAG="dirService";
  9.     private int n=0;
  10.     //用来计数的线程
  11.     private count thread;

  12.     @Override
  13.     public IBinder onBind(Intent intent) {
  14.         return null;
  15.     }

  16.     public void onCreate(){
  17.         super.onCreate();
  18.         Log.d(TAG,"oncreate");
  19.         thread=new count();
  20.     }
  21.     public void onStart(Intent intent,int startId){
  22.         Log.d(TAG,"onstart");
  23.         if(intent!=null){
  24.             //获取传送来的参数,并根据参数进行对应的操作
  25.             Bundle bundle=intent.getExtras();
  26.             int act=bundle.getInt("act");
  27.             Log.d(TAG,"act is:"+act);
  28.             switch(act){
  29.                 case 1:
  30.                     start();
  31.                     break;
  32.                 case 2:
  33.                     stop();
  34.                     break;
  35.             }
  36.         }
  37.     }
  38.     /*
  39.      * 线程类
  40.      */
  41.     class count extends Thread{
  42.         //控制线程的结束
  43.         private boolean pause=false;
  44.         public void setPause(boolean tof){
  45.             pause=tof;
  46.         }
  47.         public boolean getPauseStatues(){
  48.             return pause;
  49.         }

  50.         public void run(){
  51.             while(!pause){
  52.                 try {
  53.                     Thread.sleep(1000);
  54.                 } catch (InterruptedException e) {
  55.                     e.printStackTrace();
  56.                 }
  57.                 //每隔一秒钟输出加一后的值
  58.                 n++;
  59.                 Log.d(TAG,"n is:"+n);
  60.             }
  61.         }
  62.     }
  63.     /*
  64.      * 结束线程的执行
  65.      */
  66.     private void stop() {
  67.         thread.setPause(true);
  68.     }
  69.     /*
  70.      * 重新启动线程
  71.      */
  72.     private void start() {
  73.       //如果前面有线程在执行,则重新启动线程
  74.       if(thread.getPauseStatues()==true){
  75.           thread=new count();
  76.           thread.setPause(false);
  77.       }
  78.        thread.start();
  79.        Log.d(TAG,String.valueOf(thread.getPauseStatues()));
  80.     }
  81. }
        该界面的效果如下图所示:


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



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


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

阅读(4245) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~