android之旅-Intent和BroadcastReceiver(修改了网上文章很多不足,重点参考了android4高级编程)
一、Intent作用及分类
Intent是一种消息传递机制,可以在程序内及程序间使用,主要用法为:①使用类名显式启动一个service或Activity②在①的基础上执行一个动作的intent,并进行相关处理③广播某个时间已经发生。
二、使用Intent启动Activity
1、显式启动一个Activity
所谓显式启动,即显式指定我们要启动Activity的类名,比如我们要在Mainactivity中的Button被按下时,打开IntentActivity,就可以使用下面的代码:
<span style="white-space:pre"> </span>if(v==btn1) { Intent intent=new Intent(); intent.setClass(MainActivity.this, IntentActivity.class); startActivity(intent); }注意,所有的Activity都存储于一个Activity栈,当我们调用startActivity后,IntentActivity将会经过Creat start resume最终运行,并且IntentActivity会移动到Acticity栈的顶部。但是当我们按下back(或在代码执行finish())会从Activity栈栈顶依次删除Activity。
2、隐式启动Activity
隐式启动Activity即匿名启动某一恰当的程序组件来响应动作请求。如我们要隐式的启动打开联系人的Activity:
//隐式选择联系人,注意使用startActivity并不能启动界面 Intent intent=new Intent(Intent.ACTION_PICK,Uri.parse("content://contacts/people")); startActivityForResult(intent,PICK_CONTACT_SUBACTIVITY);3、启动Activity并捕获子Activity返回的结果
在上文我们可以看出,单纯使用startActivity MainActivity并不能得到IntentActivity进行处理后的结果。这时我们需要startActivityForResult:
但是仅仅使用这个接口还不够,我们需要一个接口来监听结构,这时,我们就需要重载MainActivity中的protected void onActivityResult(int requestCode, int resultCode, Intent data):
在MainActivity中:
<pre name="code" class="java"><pre name="code" class="java">//定义intent识别码 private static final int SHOW_SUBACTIVITY=1;<pre name="code" class="java">Intent intent=new Intent(); intent.setClass(MainActivity.this, IntentActivity.class); //传入识别码唯一标识SHOW_SUBACTIVITY,启动intent,以便获取下一页面返回的结果 startActivityForResult(intent, SHOW_SUBACTIVITY);
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // TODO Auto-generated method stub super.onActivityResult(requestCode, resultCode, data); if(requestCode==SHOW_SUBACTIVITY) { switch (resultCode) { case RESULT_CANCELED: { Bundle bd=data.getExtras(); edittxt.setText(bd.getString("text")); break; } case RESULT_OK: { Bundle bd=data.getExtras(); edittxt.setText(bd.getString("text")); break; } default: break; } } }
在IntentActivity中:
switch(v.getId()) { case R.id.resultcancel: { Intent intent=new Intent(); intent.setClass(IntentActivity.this, MainActivity.class); intent.putExtra("text", "cancel:i am from intentactivity!and pass back me on childactivity finished!"); setResult(RESULT_CANCELED,intent); finish(); break; } case R.id.resultok: { Intent intent=new Intent(); intent.setClass(IntentActivity.this, MainActivity.class); intent.putExtra("text", "ok: am from intentactivity!and pass back me on childactivity finished!"); setResult(RESULT_OK,intent); finish(); break; } default: break; }解析:我们在startActivityForResult(intent, SHOW_SUBACTIVITY);传入SHOW_SUBACTIVITY,其实就是一个大于0的整数,用来标识相应的Intent;为了接受Result,对onActivityResult(int requestCode, int resultCode, Intent data) 进行重写,注意,requestCode就是Intent的标识符,即为上文中的SHOW_SUNACTIVITY,resultCode即为IntentActivity中的setResult(RESULT_OK,intent);传回的Result值 -RESULT_OK,date即为setResult(RESULT_OK,intent);传回的intent。
三、使用Intent广播事件
1、最基本的广播事件发送与接受:
广播的发送,很简单,生成一个Intent,设置Action,直接进行广播:
<span style="white-space:pre"> </span>public static final String BROAD_UI_STRING="com.example.intentbraodcast.BROAD_UI";
<span style="white-space:pre"> </span>Intent intent=new Intent(BROAD_UI_STRING); intent.putExtra("str", "update ui by broadcast!"); sendBroadcast(intent);
广播的注册,最好在广播的发送前注册广播:
<span style="white-space:pre"> </span>//注册Broadcast Receiver registerReceiver(new MyBroadcastReceiver, new IntentFilter(BROAD_UI_STRING));
注:上文中的 BROAD_UI_STRING就是一个自定义的独一无二的字符串,由于广播不但可用于应用程序内部交换数据,还可用于系统间应用交换数据,故一般用传统的包名前缀法来命名。
进行注册以前,我们需要实现自己的接收器,继承BroadcastReceiver即可,我们对广播出的Intent绑定的数据再次进行处理
public class MyBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //TODO: React to the Intent received. String actionString=intent.getAction(); if (actionString.equals(BROAD_UI_STRING)) { //改变下一个activity中的值 String str=intent.getStringExtra("str"); Intent newIntent=new Intent(); newIntent.setClass(MainActivity.this,IntentActivity.class ); newIntent.putExtra("str", str); context.startActivity(newIntent); } else if(actionString.equals(LOCAL_ACTION)) { edittxt.setText(intent.getStringExtra("str")); } } }广播的注销:在我们不再广播时,通常是界面挂起或停止时,需要对接收器进行注销:
@Override protected void onPause() { unregisterReceiver(receiver); super.onPause(); }需要注意的是,接收器中的处理程序需要在5秒钟内完成,否则会显示Force CLose的对话框。很多时候,我们希望当我们的应用程序在关闭时也能响应一些广播,需要在Manifest中的application节点添加一个receiver标签,指定接收器类名和过滤器标识符:
<receiver android:name=".MyBroadcastReceiver" <intent-filter> <action android:name="packagename.classname.BROAD_UI_STRING" /> </intent-filter> </receiver>这样,即使我们的应用程序处于关闭状态也能响应广播。
2、有序广播
3、广播Sticky Intent,在一些教程仍出现,但在android 5.0以后会渐渐废弃,故不再讨论。
4、LocalBroadcastManager(局部广播管理器)
顾名思义,其用于局部数据的消息驱动,是一种轻量级的handler,更高效的广播模型。
操作过程与普通广播管理器类似,只不过要先获取LocalBroadcastManager:
lbm=LocalBroadcastManager.getInstance(MainActivity.this);发送时将sendBroadcast改为lbm.sendBroadcast,注册时将registerReceiver改为lbm.registerReceiver,注销时将unregisterReceiver改为lbm.unregisterReceiver
下面为示例的全部代码,工程文件我也会放到最后:
package com.example.intentandbroadcast; import android.R.string; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.Uri; import android.os.Bundle; import android.support.v4.content.LocalBroadcastManager; import android.view.*; import android.view.View.OnClickListener; import android.widget.*; @SuppressWarnings("unused") public class MainActivity extends Activity { Button btn1; Button btn2,btn3,btn4,btn_broad_ui,btn_local_broad; EditText edittxt; TextView tv; LocalBroadcastManager lbm; MyBroadcastReceiver receiver; //定义intent识别码 private static final int SHOW_SUBACTIVITY=1; private static final int PICK_CONTACT_SUBACTIVITY=2; public static final String BROAD_UI_STRING="com.example.intentbraodcast.BROAD_UI"; public static final String LOCAL_ACTION="com.example.intentbraodcast.LOCAL_ACTION"; void getviewdefinition() { btn1=(Button)findViewById(R.id.btn1); btn2=(Button)findViewById(R.id.btn2); btn3=(Button)findViewById(R.id.btn3); btn4=(Button)findViewById(R.id.btn4); btn_broad_ui=(Button)findViewById(R.id.btn_broad_ui); edittxt=(EditText)findViewById(R.id.edittext); tv=(TextView)findViewById(R.id.textview); btn_local_broad=(Button)findViewById(R.id.btn_local_broad_ui); lbm=LocalBroadcastManager.getInstance(MainActivity.this); receiver=new MyBroadcastReceiver(); } public class OnButtonClick implements OnClickListener { @Override public void onClick(View v) { // TODO Auto-generated method stub if(v==btn1) { Intent intent=new Intent(); intent.setClass(MainActivity.this, IntentActivity.class); //传入识别码唯一标识SHOW_SUBACTIVITY,启动intent,以便获取下一页面返回的结果 startActivityForResult(intent, SHOW_SUBACTIVITY); } else if(v==btn3) { //触发外部intent打电话 Intent intent=new Intent(Intent.ACTION_DIAL,Uri.parse("tel:13237170570")); startActivity(intent); } else if(v==btn4) { //隐式选择联系人,注意使用startActivity并不能启动界面 Intent intent=new Intent(Intent.ACTION_PICK,Uri.parse("content://contacts/people")); startActivityForResult(intent,PICK_CONTACT_SUBACTIVITY); } else if(v==btn_broad_ui) { Intent intent=new Intent(BROAD_UI_STRING); intent.putExtra("str", "update ui by broadcast!"); sendBroadcast(intent); } else if(v==btn_local_broad) { //设置本地广播,更高效: Intent intent=new Intent(LOCAL_ACTION); intent.putExtra("str", "i am created by local broadcast!"); lbm.sendBroadcast(intent); } } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getviewdefinition(); OnButtonClick btnclick=new OnButtonClick(); btn1.setOnClickListener(btnclick); btn3.setOnClickListener(btnclick); btn4.setOnClickListener(btnclick); btn_broad_ui.setOnClickListener(btnclick); btn_local_broad.setOnClickListener(btnclick); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); //注册Broadcast Receiver registerReceiver(receiver, new IntentFilter(BROAD_UI_STRING)); //注册local broadcast lbm.registerReceiver(receiver, new IntentFilter(LOCAL_ACTION)); } @Override protected void onPause() { unregisterReceiver(receiver); lbm.unregisterReceiver(receiver); super.onPause(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // TODO Auto-generated method stub super.onActivityResult(requestCode, resultCode, data); if(requestCode==SHOW_SUBACTIVITY) { switch (resultCode) { case RESULT_CANCELED: { Bundle bd=data.getExtras(); edittxt.setText(bd.getString("text")); break; } case RESULT_OK: { Bundle bd=data.getExtras(); edittxt.setText(bd.getString("text")); break; } default: break; } } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } public class MyBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //TODO: React to the Intent received. String actionString=intent.getAction(); if (actionString.equals(BROAD_UI_STRING)) { //改变下一个activity中的值 String str=intent.getStringExtra("str"); Intent newIntent=new Intent(); newIntent.setClass(MainActivity.this,IntentActivity.class ); newIntent.putExtra("str", str); context.startActivity(newIntent); } else if(actionString.equals(LOCAL_ACTION)) { edittxt.setText(intent.getStringExtra("str")); } } } }
package com.example.intentandbroadcast; import java.security.PublicKey; import com.example.intentandbroadcast.MainActivity.MyBroadcastReceiver; import android.app.Activity; import android.app.PendingIntent.CanceledException; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.support.v4.content.LocalBroadcastManager; import android.view.*; import android.view.View.OnClickListener; import android.widget.*; public class IntentActivity extends Activity { Button cancel,ok,btn_local; TextView txtintentTextView; IntentFilter filter; String stickystring; void getdefinition() { cancel=(Button)findViewById(R.id.resultcancel); ok=(Button)findViewById(R.id.resultok); btn_local=(Button)findViewById(R.id.btn_localintent); txtintentTextView=(TextView)findViewById(R.id.textintent); } public class OnBtnClick implements OnClickListener{ @Override public void onClick(View v) { // TODO Auto-generated method stub switch(v.getId()) { case R.id.resultcancel: { Intent intent=new Intent(); intent.setClass(IntentActivity.this, MainActivity.class); intent.putExtra("text", "cancel:i am from intentactivity!and pass back me on childactivity finished!"); setResult(RESULT_CANCELED,intent); finish(); break; } case R.id.resultok: { Intent intent=new Intent(); intent.setClass(IntentActivity.this, MainActivity.class); intent.putExtra("text", "ok: am from intentactivity!and pass back me on childactivity finished!"); setResult(RESULT_OK,intent); finish(); break; } default: break; } } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //雷区,这个启动的xml打错了 调了好久 setContentView(R.layout.activity_intent); getdefinition(); //测试startactivyforresult cancel.setOnClickListener(new OnBtnClick()); ok.setOnClickListener(new OnBtnClick()); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }eclipse工程地址:http://download.csdn.net/detail/tianyuan521521/8604875
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。