Android的最重要的组件式service和activity,那么在使用的过程中,我们最常遇到的问题是他们之间的通信问题。当然今天我们不研究底层的实现问题,我从上层的应用的如何使用的角度进行研究。
首先Activity调用Service
这个是比较基础的,它有两种常见的方法;
第一, 通过Intent,这个比较简单了,可以指定package name和class name的方式来调用,Intent.setClassName这个成员即可。通过putString来装载数据,startService(intent)即可例子如下:
Intent regIntent = new Intent(“com.service”);
regIntent.putExtra(“data”, "helloData");
startService(regIntent);
第二, 通过IPC,这个比较麻烦,一般用不着,这里不谈
但是,反过来,Service如何将一些状态告诉Activity呢?方法有两种
第一、 service 通过广播的形式发送broadcast,我们写一个broadcastReceiver即可,通常的情况,将broadcastReceiver写成Activity的内部类,这个onReceiver可以直接调用activity的方法来更新界面。但是内部类只能采用代码注册的方法registerReceiver(),不能再AndroidManifest.xml文件中进行静态的声明,因为内部类要依赖于外部类而存在的。如果你一定要用AndroidManifest来注册receiver,那么只能把broadcastReceiver写成单独的文件的public类。这时候,你想更新界面就比较麻烦了,你只能自己把你要更新的activity运行起来,然后再向这个activity的内部类发广播的消息来更新界面
第二、 service直接向activity发intent。在service里面进行startActivity是属于在Activity外startActivity即在task外启动activity,因此,必须在intent加入一个参数如下:Intent intentSend = new Intent(Constants.ACTION_STATUS);
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent1.putExtra(“statues“,“end“);
context.startActivity(intent1);
但是此时会引发的一个问题是,多次startActivity会导致很多的activity实现被运行,这肯定不是我们要的,我只要一个Activity就可,此时,我们要在androidManifest里面对这个activity的launchMode设置为singleInstance
<activity android:name="com.demo.Activity"
android:label="@string/online" android:launchMode="singleInstance">
记住啦,有人设置为singleTask,也可以,但他们有一点区别。
同时记住要更新intent,这样getInstent才可以得到每次的新实例
@Override
protected void onNewIntent (Intent intent){
setIntent(intent);
}
--------------------------------------------
在用Service下载文件时,一个问题就是Service没有界面,如何通知用户当前下载的进度,Service直接向Activity传数据有点麻烦,于是eoe想到了用Broadcast,Service广播,Activity负责接收,再对接收到的数据进行处理,就达到了我们的目的。
先注册Receiver,然后开始Service,上面的TextView和ProgressBar就会随着Service传过来的值变,解除注册Receiver或者结束Service后不会再变。
Service代码:
package com.services;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class TestService extends Service {
boolean isStop=false;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Log.i("TAG","绑定");
return null;
}
public void onCreate(){
Log.i("TAG","Services onCreate");
super.onCreate();
}
public void onStart(Intent intent,int startId){
Log.i("TAG","Services onStart");
super.onStart(intent, startId);
new Thread(){//新建线程,每隔1秒发送一次广播,同时把i放进intent传出
public void run(){
int i=0;
while(!isStop){
Intent intent=new Intent();
intent.putExtra("i", i);
i++;
intent.setAction("android.intent.action.test");//action与接收器相同
sendBroadcast(intent);
Log.i("TAG",String.valueOf(i));
try {
sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
}
@Override
public void onDestroy() {
Log.i("TAG","Services onDestory");
isStop=true;//即使service销毁线程也不会停止,所以这里通过设置isStop来停止线程
super.onDestroy();
}
}
Activity代码:
package com.services;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
public class main extends Activity {
/** Called when the activity is first created. */
Button b1,b2,b3,b4;
TestService mService;
ProgressBar pb;
MyReceiver receiver;
TextView tv;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
b1=(Button)findViewById(R.id.b1);
b2=(Button)findViewById(R.id.b2);
b3=(Button)findViewById(R.id.b3);
b4=(Button)findViewById(R.id.b4);
b1.setOnClickListener(l1);
b2.setOnClickListener(l2);
b3.setOnClickListener(l3);
b4.setOnClickListener(l4);
pb=(ProgressBar)findViewById(R.id.pb);
tv=(TextView)findViewById(R.id.tv);
}
public class MyReceiver extends BroadcastReceiver {
//自定义一个广播接收器
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
System.out.println("OnReceiver");
Bundle bundle=intent.getExtras();
int a=bundle.getInt("i");
pb.setProgress(a);
tv.setText(String.valueOf(a));
//处理接收到的内容
}
public MyReceiver(){
System.out.println("MyReceiver");
//构造函数,做一些初始化工作,本例中无任何作用
}
}
OnClickListener l1=new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
startService(new Intent(main.this, TestService.class));
//开始服务
}
};
OnClickListener l2=new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
stopService(new Intent(main.this, TestService.class));
//结束服务
}
};
OnClickListener l3=new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
//注册接收器
receiver=new MyReceiver();
IntentFilter filter=new IntentFilter();
filter.addAction("android.intent.action.test");
main.this.registerReceiver(receiver,filter);
}
};
OnClickListener l4=new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
main.this.unregisterReceiver(receiver);
//解除注册接收器
}
};
}
首先Activity调用Service
这个是比较基础的,它有两种常见的方法;
第一, 通过Intent,这个比较简单了,可以指定package name和class name的方式来调用,Intent.setClassName这个成员即可。通过putString来装载数据,startService(intent)即可例子如下:
Intent regIntent = new Intent(“com.service”);
regIntent.putExtra(“data”, "helloData");
startService(regIntent);
第二, 通过IPC,这个比较麻烦,一般用不着,这里不谈
但是,反过来,Service如何将一些状态告诉Activity呢?方法有两种
第一、 service 通过广播的形式发送broadcast,我们写一个broadcastReceiver即可,通常的情况,将broadcastReceiver写成Activity的内部类,这个onReceiver可以直接调用activity的方法来更新界面。但是内部类只能采用代码注册的方法registerReceiver(),不能再AndroidManifest.xml文件中进行静态的声明,因为内部类要依赖于外部类而存在的。如果你一定要用AndroidManifest来注册receiver,那么只能把broadcastReceiver写成单独的文件的public类。这时候,你想更新界面就比较麻烦了,你只能自己把你要更新的activity运行起来,然后再向这个activity的内部类发广播的消息来更新界面
第二、 service直接向activity发intent。在service里面进行startActivity是属于在Activity外startActivity即在task外启动activity,因此,必须在intent加入一个参数如下:Intent intentSend = new Intent(Constants.ACTION_STATUS);
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent1.putExtra(“statues“,“end“);
context.startActivity(intent1);
但是此时会引发的一个问题是,多次startActivity会导致很多的activity实现被运行,这肯定不是我们要的,我只要一个Activity就可,此时,我们要在androidManifest里面对这个activity的launchMode设置为singleInstance
<activity android:name="com.demo.Activity"
android:label="@string/online" android:launchMode="singleInstance">
记住啦,有人设置为singleTask,也可以,但他们有一点区别。
同时记住要更新intent,这样getInstent才可以得到每次的新实例
@Override
protected void onNewIntent (Intent intent){
setIntent(intent);
}
--------------------------------------------
在用Service下载文件时,一个问题就是Service没有界面,如何通知用户当前下载的进度,Service直接向Activity传数据有点麻烦,于是eoe想到了用Broadcast,Service广播,Activity负责接收,再对接收到的数据进行处理,就达到了我们的目的。
先注册Receiver,然后开始Service,上面的TextView和ProgressBar就会随着Service传过来的值变,解除注册Receiver或者结束Service后不会再变。
Service代码:
package com.services;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class TestService extends Service {
boolean isStop=false;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Log.i("TAG","绑定");
return null;
}
public void onCreate(){
Log.i("TAG","Services onCreate");
super.onCreate();
}
public void onStart(Intent intent,int startId){
Log.i("TAG","Services onStart");
super.onStart(intent, startId);
new Thread(){//新建线程,每隔1秒发送一次广播,同时把i放进intent传出
public void run(){
int i=0;
while(!isStop){
Intent intent=new Intent();
intent.putExtra("i", i);
i++;
intent.setAction("android.intent.action.test");//action与接收器相同
sendBroadcast(intent);
Log.i("TAG",String.valueOf(i));
try {
sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
}
@Override
public void onDestroy() {
Log.i("TAG","Services onDestory");
isStop=true;//即使service销毁线程也不会停止,所以这里通过设置isStop来停止线程
super.onDestroy();
}
}
Activity代码:
package com.services;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
public class main extends Activity {
/** Called when the activity is first created. */
Button b1,b2,b3,b4;
TestService mService;
ProgressBar pb;
MyReceiver receiver;
TextView tv;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
b1=(Button)findViewById(R.id.b1);
b2=(Button)findViewById(R.id.b2);
b3=(Button)findViewById(R.id.b3);
b4=(Button)findViewById(R.id.b4);
b1.setOnClickListener(l1);
b2.setOnClickListener(l2);
b3.setOnClickListener(l3);
b4.setOnClickListener(l4);
pb=(ProgressBar)findViewById(R.id.pb);
tv=(TextView)findViewById(R.id.tv);
}
public class MyReceiver extends BroadcastReceiver {
//自定义一个广播接收器
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
System.out.println("OnReceiver");
Bundle bundle=intent.getExtras();
int a=bundle.getInt("i");
pb.setProgress(a);
tv.setText(String.valueOf(a));
//处理接收到的内容
}
public MyReceiver(){
System.out.println("MyReceiver");
//构造函数,做一些初始化工作,本例中无任何作用
}
}
OnClickListener l1=new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
startService(new Intent(main.this, TestService.class));
//开始服务
}
};
OnClickListener l2=new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
stopService(new Intent(main.this, TestService.class));
//结束服务
}
};
OnClickListener l3=new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
//注册接收器
receiver=new MyReceiver();
IntentFilter filter=new IntentFilter();
filter.addAction("android.intent.action.test");
main.this.registerReceiver(receiver,filter);
}
};
OnClickListener l4=new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
main.this.unregisterReceiver(receiver);
//解除注册接收器
}
};
}