当前位置: 首页 > news >正文

河南省住房与城乡建设部网站电子商务企业网站的推广方式

河南省住房与城乡建设部网站,电子商务企业网站的推广方式,个人注册公司的条件,英文网站怎么推广第5章 使用Intent和IntentFilter通信 本章要点 理解Intent对于Android应用的作用使用Intent启动系统组件Intent的Component属性的作用Intent的Action属性的作用Intent的Category属性的作用为指定Action、Category的Intent配置对应的intent-filterIntent的Data属性Intent的Typ…第5章 使用Intent和IntentFilter通信 本章要点 理解Intent对于Android应用的作用使用Intent启动系统组件Intent的Component属性的作用Intent的Action属性的作用Intent的Category属性的作用为指定Action、Category的Intent配置对应的intent-filterIntent的Data属性Intent的Type属性为指定Data、Type的Intent配置对应的intent-filterIntent的Extra属性Intent的Flag属性 在前面介绍Activity时我们已经多次使用了Intent。当一个Activity需要启动另一Activity时程序并没有直接告诉系统要启动哪个Activity而是通过Intent来表达自己的意图需要启动哪个Activity。Intent的中文意思即为“意图”。 此时可能会有读者产生疑问假如甲Activity需要启动另一Activity为什么不直接使用一个类似于startActivity(Class activityClass)的方法呢这样岂不是更简单明了实际上这种方式虽然简洁但却明显背离了Android的设计理念。Android使用Intent来封装程序的“调用意图”无论是启动Activity、Service组件还是BroadcastReceiverAndroid都采用统一的Intent对象来封装这些“启动意图”这为开发者提供了一致的编程模型。 此外使用Intent还有一个好处在某些情况下应用程序可能只想启动具有某种特征的组件而不想与某个具体组件耦合。如果直接使用startActivity(Class activityClass)这种方法来启动特定组件势必造成一种硬编码耦合这不利于实现更高层次的解耦。 如果读者曾有过Spring MVC、Struts2等MVC框架的编程经验那么一定可以很好地理解Intent的设计。当MVC框架的控制器处理完用户请求后并不会直接返回特定的视图页面而是返回一个逻辑视图名。开发者可以在配置文件中将该逻辑视图映射到任意的物理视图资源。Android系统中的Intent设计有点类似于MVC框架中的逻辑视图设计。 总之Intent封装了Android应用程序中启动某个组件的“意图”。不仅如此Intent还是应用程序组件之间通信的重要媒介。正如在前面示例中所见两个Activity可以将需要交换的数据封装成Bundle对象然后通过Intent来携带这个Bundle对象从而实现两个Activity之间的数据交换。 5.1 Intent对象简述 Android的应用程序包含三种重要组件Activity、Service、BroadcastReceiver。应用程序采用一致的方式来启动这些组件——都是依靠Intent来启动的。Intent封装了程序想要启动组件的意图并可用于与被启动的组件交换信息。 表5.1 使用Intent启动不同组件的方法 组件类型启动方法ActivitystartActivity(Intent intent)startActivityForResult(Intent intent, int requestCode)ServiceComponentName startService(Intent service)boolean bindService(Intent service, ServiceConnection conn, int flags)BroadcastReceiversendBroadcast(Intent intent)sendBroadcast(Intent intent, String receiverPermission)sendOrderedBroadcast(Intent intent, String receiverPermission)sendStickyBroadcast(Intent intent)sendStickyOrderedBroadcast(Intent intent, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) 在上一章中我们已经介绍了如何使用Intent来启动Activity的示例。至于如何使用Intent来启动其他两种组件后续章节中会有相关示例此处暂不深入介绍。 Intent对象大致包含Component、Action、Category、Data、Type、Extra和Flag这七种属性其中Component用于明确指定需要启动的目标组件而Extra则用于“携带”需要交换的数据。 接下来我们将详细介绍Intent对象各属性的作用。 5.2 Intent 的属性及intent-filter 配置 Intent代表了Android应用的启动“意图”Android 应用将会根据Intent来启动指定组件至于到底启动哪个组件则取决于Intent的各属性。下面将详细介绍Intent的各属性值以及Android如何根据不同属性值来启动相应的组件。 5.2.1 Component 属性 Intent的Component属性需要接受一个ComponentName对象ComponentName对象包含如下几个构造器 ComponentName(String pkg, String cls)创建pkg所在包下的cls类所对应的组件。ComponentName(Context pkg, String cls)创建pkg所对应的包下的cls类所对应的组件。ComponentName(Context pkg, Class? cls)创建pkg所对应的包下的cls类所对应的组件。 这些构造器的本质是相同的这说明创建一个ComponentName需要指定包名和类名这样就可以唯一地确定一个组件类从而应用程序即可根据给定的组件类启动特定的组件。 除此之外Intent还包含了如下三个方法 setClass(Context packageContext, Class? cls)设置该Intent将要启动的组件对应的类。setClassName(Context packageContext, String className)设置该Intent将要启动的组件对应的类名。setClassName(String packageName, String className)设置该Intent将要启动的组件对应的类名。 提示: Android应用的Context代表了访问该应用环境信息的接口而Android应用的包名则作为应用的唯一标识。因此Android应用的Context对象与该应用的包名有对应关系。上面三个setClass()方法正是通过Context或String指定组件的包名和实现类。 指定Component属性的Intent已经明确了它将要启动哪个组件因此这种Intent也被称为显式Intent没有指定Component属性的Intent被称为隐式Intent——隐式Intent没有明确指定要启动哪个组件应用将会根据Intent指定的规则去启动符合条件的组件但具体是哪个组件则不确定。 提示: 例如一个女孩子有找男朋友的意图此时有两种方式来表达她的意图 她已经芳心暗许明确地告诉父母“我要找‘梁山伯’做男朋友”这种方式被称为显式Intent。她告诉父母要找“高”“富”“帅”做男朋友至于到底是谁不重要只要符合这三个条件即可这种方式被称为隐式Intent。 下面的示例程序示范了如何通过显式Intent指定了Component属性来启动另一个Activity。 public class MainActivity extends Activity {Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button bn findViewById(R.id.bn);//为bn按钮绑定事件监听器bn.setOnClickListener(view - {// 创建一个ComponentName对象ComponentName comp new ComponentName(MainActivity.this, SecondActivity.class);Intent intent new Intent();// 为Intent设置Component属性intent.setComponent(comp);startActivity(intent);});} }上面程序中的三行代码用于创建ComponentName对象并将该对象设置成Intent对象的Component属性这样应用程序即可根据该Intent的“意图”去启动指定组件。 实际上上面三行代码完全可以简化为如下形式 // 根据指定组件类来创建Intent Intent intent new Intent(MainActivity.this, SecondActivity.class);从上面的代码可以看出当需要为Intent设置Component属性时实际上Intent已经提供了一个简化的构造器这样方便程序直接指定启动其他组件。 当程序通过Intent的Component属性明确指定了启动哪个组件启动特定组件时被启动组件几乎不需要使用intent-filter元素进行配置。 程序的SecondActivity也很简单它的界面布局中只包含一个简单的文本框用于显示该Activity对应的Intent的Component属性的包名、类名。该Activity的代码如下 public class SecondActivity extends Activity {Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_second);TextView show findViewById(R.id.show);// 获取该Activity对应的Intent的Component属性ComponentName comp getIntent().getComponent();// 显示该ComponentName对象的包名、类名show.setText(组件包名为 comp.getPackageName() \n组件类名为 comp.getClassName());} }运行上面的程序通过第一个Activity中的按钮进入第二个Activity中将看到如图5.1所示的界面。 5.2.2 Action、Category 属性与intent-filter配置 Intent的Action、Category属性的值都是一个普通的字符串其中Action代表该Intent所要完成的一个抽象“动作”而Category则用于为Action增加额外的附加类别信息。通常Action属性会与Category属性结合使用。 Action要完成的只是 一个抽象动作这个动作具体由哪个组件或许是Activity或许是BroadcastReceiver来完成Action这个字符串本身并不管。比如Android提供的标准ActionIntent.ACTION_VIEW它只表示一个抽象的查看操作但具体查看什么、启动哪个Activity来查看Intent.ACTION_VIEW并不知道这取决于Activity的intent-filter配置。只要某个Activity的intent-filter配置中包含了该ACTION_VIEW该Activity就有可能被启动。 提示: 有过Struts2开发经验的读者都知道当Struts2的Action处理用户请求结束后Action并不会直接指定“跳转”到哪个Servlet通常是JSP但JSP的本质就是Servlet。Action的处理方法只是返回一个普通字符串然后在配置文件中配置该字符串对应到哪个Servlet。Struts2采用这种设计思路是为了把Action与呈现视图的Servlet分离开。类似地Intent通过指定Action属性属性值其实就是一个普通字符串就可以把该Intent与具体的Activity分离从而提供高层次的解耦。 下面通过一个简单的示例来示范Action属性就是普通字符串的作用。下面程序的第一个Activity非常简单它只包括一个普通按钮当用户单击该按钮时程序会“跳转”到第二个Activity——但第一个Activity指定跳转的Intent时并不以“硬编码”的方式指定要跳转的目标Activity而是为Intent指定Action属性。 public class MainActivity extends Activity {public static final String CRAZYIT_ACTION org.crazyit.intent.action.CRAZYIT_ACTION;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button bn findViewById(R.id.bn);// 为bn按钮绑定事件监听器bn.setOnClickListener(view - {// 创建Intent对象Intent intent new Intent();// 为Intent设置Action属性(属性值就是一个普通字符串)intent.setAction(MainActivity.CRAZYIT_ACTION);startActivity(intent);});} }上面程序中的代码指定了根据Intent来启动Activity但该Intent并未以“硬编码”的方式指定要启动哪个Activity从上面程序中无法看出该程序将要启动哪个Activity。那么到底程序会启动哪个Activity呢这取决于Activity配置中intent-filter元素的配置。 intent-filter元素是AndroidManifest.xml文件中activity元素的子元素前面已经介绍过activity元素用于为应用程序配置Activityactivity的intent-filter子元素则用于配置该Activity所能“响应”的Intent。 intent-filter元素里通常可包含如下子元素 0-N个action子元素。0-N个category子元素。0-1个data子元素。 提示: intent-filter元素也可以是service、receiver两个元素的子元素用于表明它们可以响应的Intent。 action和category子元素的配置非常简单它们都可指定android:name属性该属性的值就是一个普通字符串。 当activity元素的intent-filter子元素里包含多个action子元素相当于指定了多个字符串时就表明该Activity能响应Action属性值为其中任意一个字符串的Intent。 还是借用前面介绍的女孩子找男朋友的例子可以把Intent中的Action、Category属性理解为她对男朋友的要求每个Intent只能指定一个Action“要求”但可以指定多个Category“要求”IntentFilter使用intent-filter元素配置则用于声明该组件比如Activity、Service、BroadcastReceiver能满足的要求每个组件可以声明自己满足多个Action要求、多个Category要求。只要某个组件能满足的要求大于、等于Intent所指定的要求那么该Intent就能启动该组件。 由于上面的程序指定启动Action属性为MainActivity.CRAZYIT_ACTION常量常量值为org.crazyit.intent.action.CRAZYIT_ACTION的Activity这就要求被启动的Activity对应的配置元素的intent-filter元素里至少包括一个如下的action子元素 action android:nameorg.crazyit.intent.action.CRAZYIT_ACTION /需要指出的是一个Intent对象最多只能包括一个Action属性程序可调用Intent的setAction(String str)方法来设置Action属性值但一个Intent对象可以包括多个Category属性程序可调用Intent的addCategory(String str)方法来为Intent添加Category属性。当程序创建Intent时该Intent默认启动Category属性值为Intent.CATEGORY_DEFAULT常量常量值为android.intent.category.DEFAULT的组件。 因此虽然上面程序中的代码并未指定目标Intent的Category属性但该Intent已有一个值为android.intent.category.DEFAULT的Category属性值因此被启动Activity对应的配置元素的intent-filter元素里至少还包括一个如下的category子元素 category android:nameandroid.intent.category.DEFAULT /下面是被启动的Activity的完整配置。 activity android:name.SecondActivity android:label第二个Activityintent-filter!-- 指定该Activity能响应Action属性值为指定字符串的Intent --action android:nameorg.crazyit.intent.action.CRAZYIT_ACTION /!-- 指定该Activity能响应Action属性值为helloWorld的Intent --action android:namehelloWorld /!-- 指定该Activity能响应Category属性值为DEFAULT的Intent --category android:nameandroid.intent.category.DEFAULT //intent-filter /activity上面Activity配置的代码指定该Activity能响应具有指定Action属性值、指定Category属性值的Intent。 上面配置代码中配置了一个实现类为SecondActivity的Activity因此程序还应该提供这个Activity代码。代码如下。 public class SecondActivity extends Activity {Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_second);TextView show findViewById(R.id.show);// 获取该Activity对应的Intent的Action属性String action getIntent().getAction();// 显示Action属性show.setText(Action为 action);} }上面的程序代码很简单它只是在启动时把启动该Activity的Intent的Action属性值显示在指定文本框内。 运行上面的程序并单击程序中的“启动指定Action、默认Category对应的Activity”按钮将看到如图5.2所示的界面。 接下来的示例程序将会示范Category属性的用法。 public class MainActivity extends Activity {// 定义一个Action常量public static final String CRAZYIT_ACTION org.crazyit.intent.action.CRAZYIT_ACTION;// 定义一个Category常量public static final String CRAZYIT_CATEGORY org.crazyit.intent.category.CRAZYIT_CATEGORY;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button bn findViewById(R.id.bn);bn.setOnClickListener(view - {Intent intent new Intent();// 设置Action属性intent.setAction(MainActivity.CRAZYIT_ACTION);// 添加Category属性intent.addCategory(MainActivity.CRAZYIT_CATEGORY);startActivity(intent);});} }上面程序指定了该Intent的Action属性值为org.crazyit.intent.action.CRAZYIT_ACTION字符串并为该Intent添加了字符串为org.crazyit.intent.category.CRAZYIT_CATEGORY的Category属性。这意味着上面的程序所要启动的目标Activity里应该包含如下action子元素和category子元素 !-- 指定该Activity能响应action为指定字符串的Intent -- action android:nameorg.crazyit.intent.action.CRAZYIT_ACTION / !-- 指定该Activity能响应category为指定字符串的Intent -- category android:nameorg.crazyit.intent.category.CRAZYIT_CATEGORY / !-- 指定该Activity能响应category为DEFAULT的Intent -- category android:nameandroid.intent.category.DEFAULT /下面是程序要启动的目标Activity所对应的配置代码。 activity android:name.SecondActivity android:label第二个Activityintent-filter!-- 指定该Activity能响应action为指定字符串的Intent --action android:nameorg.crazyit.intent.action.CRAZYIT_ACTION /!-- 指定该Activity能响应category为指定字符串的Intent --category android:nameorg.crazyit.intent.category.CRAZYIT_CATEGORY /!-- 指定该Activity能响应category为DEFAULT的Intent --category android:nameandroid.intent.category.DEFAULT//intent-filter /activity上面配置Activity时也指定该Activity的实现类为SecondActivity该实现类的代码如下 public class SecondActivity extends Activity {Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_second);TextView show findViewById(R.id.show);// 获取该Activity对应的Intent的Action属性String action getIntent().getAction();// 显示Action属性show.setText(Action为 action);TextView cate findViewById(R.id.cate);// 获取该Activity对应的Intent的Category属性SetString cates getIntent().getCategories();// 显示Category属性cate.setText(Category属性为 cates);} }上面的程序代码也很简单它只是在启动时把启动该Activity的Intent的Action、Category属性值分别显示在不同的文本框内。运行上面的程序并单击程序中的“启动指定Action、指定Category对应的Activity”按钮将看到如图5.3所示的界面。 5.2.3 指定Action、Category调用系统Activity Intent代表了启动某个程序组件的“意图”实际上Intent对象不仅可以启动本应用内程序组件也可以启动Android系统的其他应用的程序组件包括系统自带的程序组件只要权限允许。 实际上Android内部提供了大量标准的Action、Category常量其中用于启动Activity的标准的Action常量及对应的字符串如表5.2所示。 表5.2 启动Activity的标准的Action常量及对应的字符串 Action 常量对应字符串简单说明ACTION_MAINandroid.intent.action.MAIN应用程序入口ACTION_VIEWandroid.intent.action.VIEW查看指定数据ACTION_ATTACH_DATAandroid.intent.action.ATTACH_DATA指定某块数据将被附加到其他地方ACTION_EDITandroid.intent.action.EDIT编辑指定数据ACTION_PICKandroid.intent.action.PICK从列表中选择某项并返回所选数据ACTION_CHOOSERandroid.intent.action.CHOOSER显示一个Activity选择器ACTION_GET_CONTENTandroid.intent.action.GET_CONTENT让用户选择数据并返回所选数据ACTION_DIALandroid.intent.action.DIAL显示拨号面板ACTION_CALLandroid.intent.action.CALL直接向指定用户打电话ACTION_SENDandroid.intent.action.SEND向其他人发送数据ACTION_SENDTOandroid.intent.action.SENDTO向其他人发送消息ACTION_ANSWERandroid.intent.action.ANSWER应答电话ACTION_INSERTandroid.intent.action.INSERT插入数据ACTION_DELETEandroid.intent.action.DELETE删除数据ACTION_RUNandroid.intent.action.RUN运行数据ACTION_SYNCandroid.intent.action.SYNC执行数据同步ACTION_PICK_ACTIVITYandroid.intent.action.PICK_ACTIVITY用于选择ActivityACTION_SEARCHandroid.intent.action.SEARCH执行搜索ACTION_WEB_SEARCHandroid.intent.action.WEB_SEARCH执行Web搜索ACTION_FACTORY_TESTandroid.intent.action.FACTORY_TEST工厂测试的入口点ACTION_ANSWERandroid.intent.action.ANSWER应答电话 标准的Category常量及对应的字符串如表5.3所示。 表5.3 标准的Category常量及对应的字符串 Category 常量对应字符串简单说明CATEGORY_DEFAULTandroid.intent.category.DEFAULT默认的CategoryCATEGORY_BROWSABLEandroid.intent.category.BROWSABLE指定该Activity能被浏览器安全调用CATEGORY_TABandroid.intent.category.TAB指定Activity作为TabActivity的Tab页CATEGORY_LAUNCHERandroid.intent.category.LAUNCHERActivity显示顶级程序列表CATEGORY_INFOandroid.intent.category.INFO用于提供包信息CATEGORY_HOMEandroid.intent.category.HOME设置该Activity随系统启动而运行CATEGORY_PREFERENCEandroid.intent.category.PREFERENCE该Activity是参数面板CATEGORY_TESTandroid.intent.category.TEST该Activity是一个测试CATEGORY_CAR_DOCKandroid.intent.category.CAR_DOCK指定手机被插入汽车底座(硬件)时运行该ActivityCATEGORY_DESK_DOCKandroid.intent.category.DESK_DOCK指定手机被插入桌面底座(硬件)时运行该ActivityCATEGORY_CAR_MODEandroid.intent.category.CAR_MODE设置该Activity可在车载环境下使用 表5.2、表5.3所列出的都只是部分较为常用的Action常量、Category常量。关于Intent所提供的全部Action常量、Category常量应参考Android API文档中关于Intent的说明。 下面将以两个实例来介绍Intent系统Action、系统Category的用法。 实例查看并获取联系人电话 这个实例将在程序中提供一个按钮用户单击该按钮时会显示系统的联系人列表当用户单击指定联系人之后程序将会显示该联系人的名字、电话。 这个程序非常有用比如我们要开发一个发送短信的程序当用户编写短信完成之后可能需要浏览联系人列表并从联系人列表中选出短信接收人那就可以用到该程序了。 该程序的界面布局代码如下。 ?xml version1.0 encodingutf-8? LinearLayout xmlns:androidhttp://schemas.android.com/apk/res/androidandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentandroid:gravitycenter_horizontalandroid:orientationvertical!--显示联系人姓名的文本框--TextViewandroid:idid/showandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:padding10dpandroid:textSize18sp /!-- 显示联系人电话号码的文本框--TextViewandroid:idid/phoneandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:padding10dpandroid:textSize18sp /Buttonandroid:idid/bnandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:text查看联系人 / /LinearLayout上面的界面布局中包含了两个文本框、一个按钮其中按钮用于浏览系统的联系人列表并选择其中的联系人。两个文本框分别用于显示联系人的名字和电话号码。 由于该程序会用到系统的联系人应用因此读者在运行该程序之前应该先进入Android系统自带的Contacts程序并通过该程序添加几个联系人。 该程序的Activity代码如下。 public class MainActivity extends Activity {private static final int PICK_CONTACT 0;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button bn findViewById(R.id.bn);// 为bn按钮绑定事件监听器bn.setOnClickListener(view - {// 运行时获取读取联系人信息的权限requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, 0x133);});}Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {if (requestCode 0x133) {// 如果用户同意授权访问if (permissions.length 0 grantResults[0] PackageManager.PERMISSION_GRANTED) {// 创建IntentIntent intent new Intent();// 设置Intent的Action属性intent.setAction(Intent.ACTION_PICK);// 设置Intent的Type属性intent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE);// 启动Activity,并希望获取该Activity的结果startActivityForResult(intent, PICK_CONTACT);}}}Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);switch (requestCode) {case PICK_CONTACT:if (resultCode Activity.RESULT_OK) {// 获取返回的数据Uri contactData data.getData();CursorLoader cursorLoader new CursorLoader(this, contactData, null, null, null, null);// 查询联系人信息Cursor cursor cursorLoader.loadInBackground();// 如果查询到指定的联系人if (cursor ! null cursor.moveToFirst()) {String contactId cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));// 获取联系人的名字String name cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME));String phoneNumber 此联系人暂未输入电话号码;// 根据联系人查询该联系人的详细信息Cursor phones getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID contactId, null, null);if (phones ! null phones.moveToFirst()) {// 取出电话号码phoneNumber phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));}// 关闭游标if (phones ! null) phones.close();TextView show findViewById(R.id.show);// 显示联系人的名称show.setText(name);TextView phone findViewById(R.id.phone);// 显示联系人的电话号码phone.setText(phoneNumber);// 关闭游标if (cursor ! null) cursor.close();}}break;}} }提示: 该实例使用了后面章节中关于ContentProvider的知识如果读者一时看不懂这个程序可以参考后面章节的讲解进行理解。 由于上面程序需要查看系统联系人信息因此要获取系统对应的权限。首先需要在AndroidManifest.xml文件中增加如下代码来获取权限。 !--请求获取读取联系人的权限-- uses-permission android:nameandroid.permission.READ_CONTACTS /最新的Android要求在获取系统资源时不能仅靠在AndroidManifest.xml文件中申请权限而是在App运行时动态请求获取权限。因此上面按钮的单击事件处理代码中的权限代码只是在运行时动态获取权限。 当用户对应用授权完成后系统会自动激发Activity的onRequestPermissionsResult方法因此上面Activity重写了该方法来处理用户的授权结果只有当用户授权本Activity访问Contacts通讯录时本Activity才会继续定义action为Intent.ACTION_PICK、指定type的Intent并通过该Intent启动Activity如上面Activity中的代码所示。 运行上面的程序单击程序界面中的“查看联系人”按钮该应用将会向用户请求授权。如果用户同意访问联系人信息程序将会显示如图5.4所示的界面。 在图5.4所示的联系人列表中单击某个联系人系统将会自动返回上一个Activity程序会在上一个Activity中显示所选联系人的名字和电话号码如图5.5所示。 上面的Intent对象除设置了Action属性之外还设置了Type属性关于Intent的Type属性的作用5.2.4节将会进行更详细的介绍。 实例返回系统Home桌面 本实例将会提供一个按钮当用户单击该按钮时系统将会返回Home桌面就像单击模拟器右边的按钮一样。这也需要通过Intent来实现程序为Intent设置合适的Action、Category属性并根据该Intent来启动Activity即可返回Home桌面。该实例程序如下。 public class MainActivity extends Activity {Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button bn findViewById(R.id.bn);bn.setOnClickListener(view - {// 创建Intent对象Intent intent new Intent();// 为Intent设置Action、Category属性intent.setAction(Intent.ACTION_MAIN);intent.addCategory(Intent.CATEGORY_HOME);startActivity(intent);});} }上面程序中的代码设置了Intent的Action属性值为android.intent.action.MAIN字符串、Category属性值为android.intent.category.HOME字符串满足该Intent的Activity其实就是Android系统的Home桌面。因此运行上面的程序时单击“返回桌面”按钮即可返回Home桌面。 5.2.4 Data、Type属性与intent-filter配置 Data属性通常用于向Action属性提供操作的数据。Data属性接受一个Uri对象该Uri对象通常通过如下形式的字符串来表示 content://com.android.contacts/contacts/1 tel:123Uri字符串通常满足如下格式 scheme://host:port/path例如上面给出的content://com.android.contacts/contacts/1其中content是scheme部分com.android.contacts是host部分port部分被省略了/contacts/1是path部分。 Type属性用于指定该Data属性所指定Uri对应的MIME类型这种MIME类型可以是任何自定义的MIME类型只要符合abc/xyz格式的字符串即可。 Data属性与Type属性的关系比较微妙这两个属性会相互覆盖例如 如果为Intent先设置Data属性后设置Type属性那么Type属性将会覆盖Data属性。如果为Intent先设置Type属性后设置Data属性那么Data属性将会覆盖Type属性。如果希望Intent既有Data属性也有Type属性则应该调用Intent的setDataAndType方法。 下面的示例演示了Intent的Data属性与Type属性互相覆盖的情形该示例的界面布局文件很简单只是定义了三个按钮并为三个按钮绑定了事件处理函数。 下面是该示例的Activity代码。 public class MainActivity extends Activity {Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void overrideType(View source) {Intent intent new Intent();// 先为Intent设置Type属性intent.setType(abc/xyz);// 再为Intent设置Data属性覆盖Type属性intent.setData(Uri.parse(lee://www.fkjava.org:888/test));Toast.makeText(this, intent.toString(), Toast.LENGTH_LONG).show();}public void overrideData(View source) {Intent intent new Intent();// 先为Intent设置Data属性intent.setData(Uri.parse(lee://www.fkjava.org:888/mypath));// 再为Intent设置Type属性覆盖Data属性intent.setType(abc/xyz);Toast.makeText(this, intent.toString(), Toast.LENGTH_LONG).show();}public void dataAndType(View source) {Intent intent new Intent();// 同时设置Intent的Data、Type属性intent.setDataAndType(Uri.parse(lee://www.fkjava.org:888/mypath), abc/xyz);Toast.makeText(this, intent.toString(), Toast.LENGTH_LONG).show();} }上面的三个事件监听方法分别为Intent设置了Data、Type属性第一个事件监听方法先设置了Type属性再设置了Data属性这将导致Data属性覆盖Type属性单击按钮激发该事件监听方法将可以看到如图5.6所示的Toast输出。 从图5.6可以看出此时的Intent只有Data属性Type属性被覆盖了。 第二个事件监听方法先设置了Data属性再设置了Type属性这将导致Type属性覆盖Data属性单击按钮激发该事件监听方法将可以看到如图5.7所示的输出。 第三个事件监听方法同时设置了Data、Type属性这样该Intent中才会同时具有Data、Type属性。 在AndroidManifest.xml文件中为组件声明Data、Type属性都通过data元素data元素的格式如下 data android:mimeTypeandroid:schemeandroid:hostandroid:portandroid:pathandroid:pathPrefixandroid:pathPattern /上面的data元素支持如下属性 mimeType用于声明该组件所能匹配的Intent的Type属性。scheme用于声明该组件所能匹配的Intent的Data属性的scheme部分。host用于声明该组件所能匹配的Intent的Data属性的host部分。port用于声明该组件所能匹配的Intent的Data属性的port部分。path用于声明该组件所能匹配的Intent的Data属性的path部分。pathPrefix用于声明该组件所能匹配的Intent的Data属性的path前缀。pathPattern用于声明该组件所能匹配的Intent的Data属性的path字符串模板。 Intent的Type属性用于指定该Intent的要求对应组件中intent-filter元素的data子元素的mimeType属性必须与此相同才能启动该组件。 Intent的Data属性略有差异程序员为Intent指定Data属性时Data属性的Uri对象实际上可分为scheme、host、port和path部分此时并不要求被启动组件 的intent-filter的data子元素的android:scheme、android:host、android:port、android:path完全满足。 Data属性的“匹配”过程有些差别它会先检查intent-filter的data子元素然后 如果目标组件的data子元素只指定了android:scheme属性那么只要Intent的Data属性的scheme部分与android:scheme属性值相同即可启动该组件。如果目标组件的data子元素只指定了android:scheme、android:host属性那么只要Intent的Data属性的scheme、host部分与android:scheme、android:host属性值相同即可启动该组件。如果目标组件的data子元素指定了android:scheme、android:host、android:port属性那么只要Intent的Data属性的scheme、host、port部分与android:scheme、android:host、android:port属性值相同即可启动该组件。 提示: 如果data子元素只有android:port属性没有指定android:host属性那么android:port属性将不会起作用。 如果目标组件的data子元素只指定了android:scheme、android:host、android:path属性那么只要Intent的Data属性的scheme、host、path部分与android:scheme、android:host、android:path属性值相同即可启动该组件。 如果data子元素只有android:path属性没有指定android:host属性那么android:path属性将不会起作用。 如果目标组件的data子元素指定了android:scheme、android:host、android:port、android:path属性那么就要求Intent的Data属性的scheme、host、port、path部分依次与android:scheme、android:host、android:port、android:path属性值相同才可启动该组件。 下面的示例测试了Intent的Data属性与data元素配置的关系该示例依次配置了如下5个Activity。 activity android:icondrawable/ic_scheme android:name.SchemeActivity android:label指定scheme的Activityintent-filteraction android:namexx /category android:nameandroid.intent.category.DEFAULT /!-- 只要Intent的Data属性的scheme是lee即可启动该Activity --data android:schemelee //intent-filter /activityactivity android:icondrawable/ic_host android:name.SchemeHostPortActivity android:label指定scheme、host、port的Activityintent-filteraction android:namexx /category android:nameandroid.intent.category.DEFAULT /!-- 只要Intent的Data属性的scheme是lee且host是www.fkjava.orgport是8888即可启动该Activity --data android:schemelee android:hostwww.fkjava.org android:port8888 //intent-filter /activityactivity android:icondrawable/ic_sp android:name.SchemeHostPathActivity android:label指定scheme、host、path的Activityintent-filteraction android:namexx /category android:nameandroid.intent.category.DEFAULT /!-- 只要Intent的Data属性的scheme是lee且host是www.fkjava.orgpath是/mypath即可启动该Activity --data android:schemelee android:hostwww.fkjava.org android:path/mypath //intent-filter /activityactivity android:icondrawable/ic_path android:name.SchemeHostPortPathActivity android:label指定scheme、host、port、path的Activityintent-filteraction android:namexx /category android:nameandroid.intent.category.DEFAULT /!-- 需要Intent的Data属性的scheme是lee且host是www.fkjava.orgport是8888path是/mypath才可启动该Activity --data android:schemelee android:hostwww.fkjava.org android:port8888 android:path/mypath //intent-filter /activityactivity android:icondrawable/ic_type android:name.SchemeHostPortPathTypeActivity android:label指定scheme、host、port、path、type的Activityintent-filteraction android:namexx /category android:nameandroid.intent.category.DEFAULT /!-- 需要Intent的Data属性的scheme是lee且host是www.fkjava.orgport是8888path是/mypathtype是abc/xyz才可启动该Activity --data android:schemelee android:hostwww.fkjava.org android:port8888 android:path/mypath android:mimeTypeabc/xyz //intent-filter /activity在上面的配置文件中配置了5个Activity这5个Activity的实现类都非常简单它们都仅在界面上显示一个TextView并不显示其他内容。关于这5个Activity的data子元素配置说明如下 第1个Activity只要Intent的Data属性的scheme是lee即可启动该Activity。第2个Activity只要Intent的Data属性的scheme是lee且host是www.fkjava.orgport是888即可启动该Activity。第3个Activity只要Intent的Data属性的scheme是lee且host是www.fkjava.orgpath是/mypath即可启动该Activity。第4个Activity需要Intent的Data属性的scheme是lee且host是www.fkjava.orgport是888path是/mypath才可启动该Activity。第5个Activity需要Intent的Data属性的scheme是lee且host是www.fkjava.orgport是8888path是/mypathtype是abc/xyz才可启动该Activity。 上面配置Activity的intent-filter元素时action子元素的name属性是随意指定的这也是必需的。如果希望data子元素能正常起作用至少要配置一个action子元素但该子元素的android:name属性值可以是任意的字符串。 下面是第1个启动Activity的方法。 public void scheme(View source) {Intent intent new Intent();// 只设置Intent的Data属性intent.setData(Uri.parse(lee://www.crazyit.org:1234/test));startActivity(intent); }上面Intent的Data属性只有scheme为lee也就是只有第1个Activity符合条件因此通过该方法启动Activity时将可以看到启动如图5.8所示的Activity。 下面是第2个启动Activity的方法。 public void schemeHostPort(View source) {Intent intent new Intent();// 只设置Intent的Data属性intent.setData(Uri.parse(lee://www.fkjava.org:8888/test));startActivity(intent); }上面Intent的Data属性scheme为lee因此第1个Activity符合条件且该Intent的Data属性的host为www.fkjava.orgport为888因此第2个Activity也符合条件。通过该方法启动Activity时将可以看到启动如图5.9所示的选择Activity界面。 下面是第3个启动Activity的方法。 public void schemeHostPath(View source) {Intent intent new Intent();// 只设置Intent的Data属性intent.setData(Uri.parse(lee://www.fkjava.org:1234/mypath));startActivity(intent); }上面Intent的Data属性scheme为lee因此第1个Activity符合条件且该Intent的Data属性的host为www.fkjava.orgpath为/mypath因此第3个Activity也符合条件。通过该方法启动Activity时将可以看到启动如图5.10所示的选择Activity界面。 下面是第4个启动Activity的方法。 public void schemeHostPortPath(View source) {Intent intent new Intent();// 只设置Intent的Data属性intent.setData(Uri.parse(lee://www.fkjava.org:8888/mypath));startActivity(intent); }上面Intent的Data属性scheme为lee因此第1个Activity符合条件且该Intent的Data属性的host为www.fkjava.orgport为888因此第2个Activity符合条件该Intent的Data属性的host为www.fkjava.orgpath为/mypath因此第3个Activity符合条件该Intent的Data属性的host为www.fkjava.orgport为888path为/mypath因此第 4个Activity也符合条件。通过该方法启动Activity时将可以看到启动如图5.11所示的选择Activity界面。 下面是第5个启动Activity的方法。 public void schemeHostPortPathType(View source) {Intent intent new Intent();// 同时设置Intent的Data、Type属性intent.setDataAndType(Uri.parse(lee://www.fkjava.org:8888/mypath), abc/xyz);startActivity(intent); }上面的Intent不仅指定了Data属性也指定了Type属性此时符合条件的只有第5个Activity。通过该方法启动Activity时将可以看到启动如图5.12所示的Activity。 实例使用Action、Data属性启动系统Activity 一旦为Intent同时指定了Action、Data属性Android就可根据指定的数据类型来启动特定的应用程序并对指定数据执行相应的操作。 下面是几个常见的Action属性、Data属性的组合 ACTION_VIEW content://com.android.contacts/contacts/1显示标识为1的联系人的信息。ACTION_EDIT content://com.android.contacts/contacts/1编辑标识为1的联系人的信息。ACTION_DIAL content://com.android.contacts/contacts/1显示向标识为1的联系人拨号的界面。ACTION_VIEW tel:123显示向指定号码123拨号的界面。ACTION_DIAL tel:123显示向指定号码123拨号的界面。ACTION_VIEW content://contacts/people/显示所有联系人列表的信息通过这种组合可以非常方便地查看系统联系人。 本实例程序示范通过同时为Intent指定Action、Data属性来启动特定程序并操作相应的数据。下面程序的界面很简单只包含3个按钮其中一个按钮用于浏览指定网页一个按钮用于编辑指定联系人信息另一个按钮用于呼叫指定号码。 public class MainActivity extends Activity {Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button bn findViewById(R.id.bn);// 为bn按钮添加一个监听器bn.setOnClickListener(view - {// 创建IntentIntent intent new Intent();// 为Intent设置Action属性intent.setAction(Intent.ACTION_VIEW);// 设置Data属性intent.setData(Uri.parse(http://www.crazyit.org));startActivity(intent);});Button edit findViewById(R.id.edit);// 为edit按钮添加一个监听器edit.setOnClickListener(view - {// 创建IntentIntent intent new Intent();// 为Intent设置Action属性动作为编辑intent.setAction(Intent.ACTION_EDIT);// 设置Data属性intent.setData(Uri.parse(content://com.android.contacts/contacts/1));startActivity(intent);});Button call findViewById(R.id.call);// 为call按钮添加一个监听器call.setOnClickListener(view - {// 创建IntentIntent intent new Intent();// 为Intent设置Action属性动作为拨号intent.setAction(Intent.ACTION_DIAL);// 设置Data属性intent.setData(Uri.parse(tel:13800138000));startActivity(intent);});} }运行上面的程序单击第一个按钮该按钮被单击时启动Intent(ActionIntent.ACTION_VIEW, Datahttp://www.crazyit.org)对应的Activity将看到打开www.crazyit.org的界面。 单击第二个按钮该按钮被单击时启动Intent(ActionIntent.ACTION_EDIT, Datacontent://com.android.contacts/contacts/1)对应的Activity将看到编辑标识为1的联系人界面。 单击第三个按钮该按钮被单击时启动Intent(ActionIntent.ACTION_DIAL, Datatel:13800138000)对应的Activity将看到程序向13800138000拨号的界面。 5.2.5 Extra属性 Intent的Extra属性通常用于在多个Action之间进行数据交换Intent的Extra属性值应该是一个Bundle对象Bundle对象就像一个Map对象它可以存入多个key-value对这样就可以通过Intent在不同Activity之间进行数据交换了。关于Extra属性的用法前面已有示例此处不再赘述。 5.2.6 Flag属性 Intent的Flag属性用于为该Intent添加一些额外的控制标志Intent可调用addFlags()方法来添加控制标志。 前面介绍启用ActionBar的程序图标返回主Activity时已经用到了Flag属性。比如前面介绍的Intent.FLAG_ACTIVITY_CLEAR_TOP标志可用于清除当前Activity栈中的Activity。 除此之外Intent还包含了如下常用的Flag标志 FLAG_ACTIVITY_BROUGHT_TO_FRONT如果通过该Flag启动的Activity已经存在下次再次启动时将只是把该Activity带到前台。例如现在Activity栈中有Activity A此时以该标志启动Activity B即Activity B是以FLAG_ACTIVITY_BROUGHT_TO_FRONT标志启动的然后在Activity B中启动Activity C、D如果此时在Activity D中再启动Activity B将直接把Activity栈中的Activity B带到前台。此时Activity栈中情形是Activity A、C、D、B。FLAG_ACTIVITY_CLEAR_TOP该Flag相当于加载模式中的singleTask通过这种Flag启动的Activity将会把要启动的Activity之上的Activity全部弹出Activity栈。例如Activity栈中包含A、B、C、D四个Activity如果采用该Flag从Activity D跳转到Activity B那么此时Activity栈中只包含A、B两个Activity。FLAG_ACTIVITY_NEW_TASK默认的启动标志该标志控制重新创建一个新的Activity。FLAG_ACTIVITY_NO_ANIMATION该标志控制启动Activity时不使用过渡动画。FLAG_ACTIVITY_NO_HISTORY该标志控制被启动的Activity将不会保留在Activity栈中。例如Activity栈中原来有A、B、C三个Activity此时在Activity C中以该Flag启动Activity DActivity D再启动Activity E此时Activity栈中只有A、B、C、E四个ActivityActivity D不会保留在Activity栈中。FLAG_ACTIVITY_REORDER_TO_FRONT该Flag控制如果当前已有Activity则直接将该Activity带到前台。例如现在Activity栈中有A、B、C、D四个Activity如果使用FLAG_ACTIVITY_REORDER_TO_FRONT标志来启动Activity B那么启动后的Activity栈中情形为A、C、D、B。FLAG_ACTIVITY_SINGLE_TOP该Flag相当于加载模式中的singleTop模式。例如原来Activity栈中有A、B、C、D四个Activity在Activity D中再次启动Activity DActivity栈中依然还是A、B、C、D四个Activity。 Android为Intent提供了大量的Flag每个Flag都有其特定的功能具体请参考关于Intent的API文档。 5.3 本章小结 本章主要介绍了Android系统中Intent的功能和用法。当Android应用需要启动某个组件时总需要借助于Intent来实现。不管是启动Activity还是启动Service、BroadcastReceiver组件Android系统都是由Intent来实现的。简单地说Android使用Intent封装了应用程序的“启动意图”但这种“意图”并未直接与任何程序组件耦合通过这种方式即可很好地提高系统的可扩展性和可维护性。学习本章需要重点掌握Intent的Component、Action、Category、Data、Type各属性的功能与用法并掌握如何在AndroidManifest.xml文件中配置intent-filter元素。
http://www.tj-hxxt.cn/news/133404.html

相关文章:

  • 网站开发开票内容专业网站制作公司地址
  • 网站的建设费计入什么科目中职网页设计与制作教材
  • 福田网站设计公司做海外网站推广
  • 网站开发英文论文网站开发需要学
  • 忻州网站制作动漫设计学校
  • 网站开发师培训创建网站论坛
  • 浙江省工程建设质量管理协会 网站天元建设集团有限公司商票兑付情况
  • 深圳建筑设计平台网站信息流广告创意
  • 榆林做网站网站建设公司盈利分析
  • 网站底部图标wordpress打赏按钮
  • 漳州网站建设哪家好天津免费建网站
  • 做年报的网站怎么登不上去了互联网企业公司简介
  • 网站建设首选九零后网络昆明网页建站平台
  • 免费舆情网站下载大全最新版大连工业大学研究生院官网
  • 网站建设合同验收标准什么企业时候做网站
  • 佛山市外贸企业高端网站设计学做网站赚钱方法
  • 网站维护属于什么专业网站流量seo
  • 阿里云服务器多个网站专科学什么专业好就业前景好
  • 网站建设申报书wordpress 仿京东主题
  • 专业装修别墅徐州网站优化
  • 做网站的网络公司厨师培训
  • cnetos 7 wordpress车辆优化管理专业网站
  • 近一周的热点新闻seo免费优化网址软件
  • 搜讯网站开发微信建微网站
  • 西安哪个公司做网站WordPress主题会包含木马吗
  • 湛江网站建设哪家优惠多网站文章要求
  • 免费网站建设免代码wordpress官方响应式主题
  • 网站开发 如何备案一小时学会网站建设
  • html 医药网站模板那里网站建设好
  • 外贸那些网站好用镇江网站制作教程