Android基础笔记(七)-页面跳转和数据传递

技术分享

Activity简介

Activity是Android的四大组件之一,它用于展示界面。它提供一个屏幕,用户可以用来交互,可以通过setContentView(View)来显示指定的控件。

在一个android应用中,一个Activity通常就是一个单独的屏幕,它上面可以显示一些控件也可以监听并处理用户的事件做出响应。Activity之间通过Intent进行通信。

Activity的简单使用

① 定义类继承Activity

② 在AndroidManifest.xml的<application>节点中声明<activity>
<application>:中lable是指程序的名字,在卸载页面显示的名字就是这个lable指定的。

<activity>中的lable是指activity的名字,如果此activity还指定了以下intent-filter,那么这个界面就会在桌面创建快捷方式,快捷方式名字就是这个activity的lable。
<category>:指定意图的类别,LAUNCHER是在桌面创建快捷方式。

<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
Activity在清单文件中的配置
①Lable属性:Activity页面的标题,界面的名字,如果此界面被创建快捷方式,则快捷方式的名字就是lable值。
②Name属性:指定的值为:包名.Activity类名。包名如果与mainfest的package一致,可以用“.”代替;或者不写。
③Intent-filter子节点:添加意图过滤,可以通过隐式意图启动。可以在桌面生成快捷方式,增加应用程序的入口。
④Icon属性:指定应用程序的图标
⑤android:theme属性:指定主题android:theme=”@android:style/Theme.Dialog”
如何让程序有多个启动入口

创建一个SecondActivity并在清单文件中声明,且修改两个<activity>android:label值。

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="com.bzh.launch.MainActivity"
        android:label="我是入口1" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name="com.bzh.launch.SecondActivity"
        android:label="我是入口2" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

测试结果图如下:
技术分享
技术分享
技术分享
我们可以看到,在应用程序清单中多了两个应用图标我是入口1我是入口2,分别打开后所对应的就是清单文件中声明的Activity

Activity之间的跳转

什么是意图?
即Intent,用于激活组件,Android的组件都可以通过intent去激活。
Activity之间的跳转分为两种

①显式意图跳转:知道跳转目标的类名,并且可以拿到其字节码对象。一般用于自己程序的内部。一般用于自己程序的内部。显式跳转不可以跳转到其他程序的页面中。

//创建一个Intent对象,并传递当前对象(Context对象)和要跳转的Activity类字节码
Intent intent = new Intent(this, SecondActivity.class);
//启动第二个Activity
startActivity(intent);
②隐式意图跳转::可以在当前程序跳转到另一个程序的页面。隐式跳转不需要引用到那个类,但是必须得知道那个界面的动作(action)和信息(category);因此,能够被隐式跳转的Activity,在清单文件中声明时必须指定动作和信息这两个属性。
显式意图是指在创建意图时指定了组件,而隐式意图则不指定组件,通过动作、类型、数据匹配对应的组件。

当我们为一个Activity增加如下的过滤器时,

<intent-filter >
     <!-- 在意图过滤器中设置action和category,当有匹配的action和category的时候启动该Activity。这里使用Android提供的默认category即可 -->
     <action android:name="com.itheima.activitySkip.SecondActivity"/>
     <category android:name="android.intent.category.DEFAULT"/>
</intent-filter>

那么想要激活这个Activity的话,需要在intent中指定动作和类型

//创建一个Intent对象
Intent intent = new Intent();
//设置Action
intent.setAction("com.bzh.SecondActivity");
//对于android.intent.category.DEFAULT类型的信息为Android系统默认的信息,省略也可以
intent.addCategory("android.intent.category.DEFAULT");
//启动Activity
startActivity(intent);

意图传递数据

Intent除了可以激活组件(启动Activity等),还可以通过封装的Bundle对象来携带数据。所以在启动一个Activity的时候,同时还可以传递数据,然后在新的Activity中可以获得意图对象以获取其中Bundle保存的数据。

Intent可传递的数据类型有: 八大基本数据类型,String,数组,ArrayList<String>, Bundle数据捆, 实现序列化接口的javabean。

实现Serizlizable可以再网络中传输
实现Parcelable可以序列化到内存中

注意: Intent传递的数据过多可能会造成跳转速度极慢甚至黑屏一会,不要用Intent传递过多的数据,会影响到应用程序的使用。

使用意图过滤器数据协议传递数据
设置数据协议和配置数据的mimeType,从而达到传递数据的目的

① 在清单文件中配置意图过滤器

<activity android:name="com.bzh.SecondActivity">
<!-- 配置意图过滤器 -->
<intent-filter >
    <!-- 在意图过滤器中设置action和category,当有匹配的action和category的时候启动该Activity -->
    <action android:name="com.bzh.SecondActivity"/>
    <!-- 设置数据协议 -->
    <data android:scheme="money"/>
    <!-- 配置数据的mimeType:必须为xxx/xxx的格式,否则会报异常  -->
    <data android:mimeType="data/mymime"/> 
</intent-filter>
</activity>

② 在FristActivity中启用意图,并使用数据协议,设置数据。

// 创建一个Intent对象
Intent intent = new Intent();
// 设置Action
intent.setAction("com.bzh.SecondActivity");
// 对于android.intent.category.DEFAULT类型的信息为Android系统默认的信息,省略也可以
intent.addCategory("android.intent.category.DEFAULT");
intent.setDataAndType(Uri.parse("money:转账100元。"), "data/mymime");

③ 在SecondActivity中使用getIntent()获取到意图,并拿到数据

//获取从当前Context对象中获取Intent
Intent intent = getIntent();//注意这个是getIntent()
//获取数据
String data = intent.getData().toString();
System.out.println(data);
使用意图的Bundle传递数据

Google在Intent中提供了大量的重载的putExtra(XX,XX)方法,帮助我们传递数据,但是我们看一下源码会发现底层用的都是Bundle对象来实现的。

public Intent putExtra(String name, char[] value) {
    if (mExtras == null) {
          mExtras = new Bundle();
      }
      mExtras.putCharArray(name, value);
      return this;
}

我们再看一下Bundle的构造函数,发现Bundle内部其实是个Map

 public Bundle() {
      mMap = new HashMap<String, Object>();
      mClassLoader = getClass().getClassLoader();
}
接下来看看在Intent中如何借助Bundle传递数据

 在发送端

//给Intent设置数据
intent.putExtra("name", "张三");
//给你Intent设置字符串类型的集合
intent.putStringArrayListExtra("list", list);
//声明一个Bundle对象,bundle内部是包装过的map集合
Bundle bundle = new Bundle();
//在Bundle对象中绑定数据
bundle.putString("pwd", "123456");
//给Intent设置Bundle对象
intent.putExtras(bundle);//通过putExtras()传递bundle

接收端

Bundle extras = intent.getExtras();//通过getExtras获取bundle
//从Bundle中获取可以为name的数据
String name = (String) extras.get("name");//再通过get()获取具体值
System.out.println("name="+name);
//从Bundle对象中获取key为pwd的数据
String pwd = (String) extras.get("pwd");
System.out.println(pwd);
//从Bundle中获取ley为list的数据
List<String> list = (List<String>) extras.get("list");

创建Activity获取返回数据

操作步骤:
①使用startActivityForResult(Intent intent, int requestCode) 方法打开Activity
②重写onActivityResult(int requestCode, int resultCode, Intent data)方法
③在被打开的Activity中调用setResult(int resultCode, Intent data)设置返回数据之后,使用finish()关闭Activity,第一个Activity就会调用onActivityResult方法
requestCode,请求码:用于区别是哪个操作启动的意图
resultCode,结果码,用于区别是哪个Activity返回的数据

如何调用系统发送短信的页面

如何能够把我们的数据传递给系统的短信页面,例如下面这个样子

技术分享

代码其实是很简单的

Intent intent = new Intent();
// 设置发送短信的动作
intent.setAction("android.intent.action.SEND");
intent.addCategory("android.intent.category.DEFAULT");
// 设置数据类型
intent.setType("text/plain");
// 使用Bundle传递数据
intent.putExtra("sms_body", content);
startActivity(intent);

但是里面有些关键信息(意图过滤器,键值),例如action、type、putExtra的key值怎么找到?其实才是个难点。

接下来就讲一下如何找到这些关键信息的思路。当前,前提是你要有Android的源码。
①我们知道,Andriod有4层架构,最上层是应用层,在原生的系统中就带有很多的应用,而短息也是应用之一。在我们的源码中,可以知道android4.4src/packages/apps就是我们系统自带的一些应用。
技术分享
②既然知道了这些,那么就找到我们的短信所在的目录把android4.4src/pagkages/apps/mms/
技术分享

③ 我们知道,清单文件中的activity下才是定义意图过滤器的地方,所以我们看一下清单文件,而且,既然是发送短信,我们再搜索一下SEND关键字,可以得到如下的结果:


<activity android:name=".ui.ComposeMessageActivity"
          android:configChanges="orientation|screenSize|keyboardHidden"
          android:windowSoftInputMode="stateHidden|adjustResize"
          android:theme="@style/MmsHoloTheme"
          android:parentActivityName=".ui.ConversationList"
          android:launchMode="singleTop" >
   ...
   <intent-filter>
       <action android:name="android.intent.action.SEND" />
       <category android:name="android.intent.category.DEFAULT" />
       <data android:mimeType="image/*" />
   </intent-filter>
   <intent-filter>
       <action android:name="android.intent.action.SEND" />
       <category android:name="android.intent.category.DEFAULT" />
       <data android:mimeType="text/plain" />
   </intent-filter>
   ...
</activity>

这样,意图过滤器的关键信息就知道了;接下来就是要在Bundle中保存数据了,那么intent.putExtras(K,V)中的K值怎找到?
既然这个是系统的应用,那么系统的代码中就应该会有类似于intent.putExtras(K,V)这样的代码,而上面的<activity name=‘...‘>中的name属性值为.ui.ComposeMessageActivity,我们又知道了具体的类是什么,那么我们搜索一下就OK了。结果如下:
技术分享

如何发送短信

发送短信的步骤相当简单,请参看下面的代码:

// 获取短信管理器
SmsManager smsManager = SmsManager.getDefault();
// 防止短信内容过长,将其内容分割开
ArrayList<String> messageList = smsManager.divideMessage(content);
for (String sms : messageList) {
    // 目标人
    String destinationAddress = contact;
    // 短信服务中心地址
    String scAddress = null;
    // 短信内容
    String text = sms;
    // 延期广播一般为NULL
    PendingIntent sentIntent = null;
    PendingIntent deliveryIntent = null;
    // 使用短信管理器发送短信
    smsManager.sendTextMessage(destinationAddress, scAddress, text, sentIntent, deliveryIntent);
}

当然,这只是很简单的示例,更为详细的请参看Android API

技术分享

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。