目录
隐式意图和显式意图:
显式意图:显式意图明确指明了启动活动的上下文和想要启动的目标活动,显式意图明确指定了Intent应该传递给哪个组件。
隐式意图:没有明确指定组件名的Intent为隐式意图。 Android系统会根据隐式意图中设置的动作(action)、类别(category)、数据(URI和数据类型)找到最合适的组件来处理这个意图。
开启自己应用的界面用显式意图,开启其他应用(一般指系统应用)的时候用隐式意图(比如拨打电话)。
显式意图安全一些,隐式意图可以通过匹配intent-filter里面的标签对应来跳转到相应的页面 。
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testactivity">
<uses-permission android:name="android.permission.CALL_PHONE" />
<application
android:allowBackup="true"
android:icon="@drawable/kakaxi"
android:label="@string/app_name"
android:roundIcon="@drawable/mingren"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="第一个activity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".TestActivity"
android:label="第二个activity">
<intent-filter>
<action android:name="mytestAction" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:mimeType="aa/bb"
android:scheme="mytestscheme" />
</intent-filter>
</activity>
<activity android:name=".Test3" />
</application>
</manifest>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/id_btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onclick"
android:text="拨打电话" />
<Button
android:id="@+id/id_btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onclick"
android:text="隐式意图跳转到TestActivity" />
<Button
android:id="@+id/id_btn3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onclick"
android:text="显式意图跳转到TestActivity" />
</LinearLayout>
MainActivity.java
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onclick(View view) {
switch (view.getId()) {
case R.id.id_btn1:
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CALL_PHONE}, 1);
} else {
call();
}
break;
case R.id.id_btn2:
// 创建意图对象
Intent intent = new Intent();
// 以下隐式意图都可以自定义
// 设置拨打的动作
intent.setAction("mytestAction");
// 设置category
intent.addCategory("android.intent.category.DEFAULT");
// 设置数据和基本类型
intent.setDataAndType(Uri.parse("mytestscheme:"), "aa/bb");// 一定要有冒号:可以后面随便加个数,和tel:类似
// 主要是为了匹配清单文件的约束
// 开启Activity,记得加上权限
startActivity(intent);
break;
case R.id.id_btn3:
Intent intent1 = new Intent(MainActivity.this, Test3.class);
// 如果是构造的空参intent,则设置包名和类名,或者构造2个参数intent
//intent1.setClassName("com.example.testactivity", "com.example.testactivity.Test3");
startActivity(intent1);
break;
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode){
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
call();
} else {
Toast.makeText(this, "you denied the permision", Toast.LENGTH_SHORT).show();
}
break;
}
}
private void call() {
// 创建意图对象
Intent intent = new Intent();
// 设置拨打的动作
intent.setAction(Intent.ACTION_CALL);
// 设置拨打的数据
intent.setData(Uri.parse("tel:" + 119));
// 开启Activity,记得加上权限
startActivity(intent);
}
}
批注:
按钮1,2为了演示隐式意图,按钮3演示显式意图
关于隐式意图:
在case R.id.id_btn2:中
intent.setData(data)和intent.setType(type)注意这两个方法会互相清除,意思就是:如果先设置setData(data)后设置setType(type),那么后设置的setType(type)会把前面setData(data)设置的内容清除掉,而且会报错,反之一样,所以如果既要设置类型与数据,那么使用public Intent setDataAndType(Uri data, String type) 这个方法。
可以配置多个意图过滤器,只要能够完整的匹配任何一个意图过滤器intent-filter,就可以跳转到那个activity
如果intent-filter里面只有<action>和<category>标签,那么只有<action>和<category>中的内容同时能够匹配上Intent中指定的action和category时,这个活动才能响应这个Intent。如果还有data标签,也要一一对应才行。
每个Intent中只能指定一个action,却能指定多个category。
关于data标签:
为什么设置数据和基本类型时intent.setDataAndType(Uri.parse("mytestscheme:"), "aa/bb");
这里一定要有冒号:后面可以随便加个数,或者不加,和tel:类似,这里不是拨打电话,所以可以不加,主要为了符合约束条件
关于显式意图:
在case R.id.id_btn3:中
Intent intent1 = new Intent(MainActivity.this, Test3.class);
startActivity(intent1);
等价于<===========>
Intent intent1 = new Intent();
intent1.setClassName("com.example.testactivity", "com.example.testactivity.Test3");
startActivity(intent1);
一般写上面那一种就可以了。
TestActivity.java
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
public class TestActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout2);
}
}
Test3.java
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
public class Test3 extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout3);
}
}
layout2.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="第二个activity"/>
</LinearLayout>
layout3.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="第三个activity"/>
</LinearLayout>
使用意图在activity之间传递数据(人品计算器):
MainActivity.java
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private EditText et_name;
private RadioGroup rg_group;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_name = (EditText) findViewById(R.id.et_name);
rg_group = (RadioGroup) findViewById(R.id.radioGroup);
}
public void click(View view) {
// 获取用户名
String name = et_name.getText().toString().trim();
if (TextUtils.isEmpty(name)) {
Toast.makeText(this, "亲,请输入姓名", Toast.LENGTH_SHORT).show();
return;
}
// 判断用户性别
int id = rg_group.getCheckedRadioButtonId();
int sex = 0;
switch (id) {
case R.id.rb_male:
sex = 1;
break;
case R.id.rb_female:
sex = 2;
break;
case R.id.rb_other:
sex = 3;
break;
}
if (sex == 0) {
Toast.makeText(this, "请选择性别", Toast.LENGTH_SHORT).show();
return;
}
// 跳转到ResultActivity页面,用显式意图跳转
Intent intent = new Intent(this, ResultActivity.class);
// 传递姓名
intent.putExtra("name", name);
// 传递性别
intent.putExtra("sex", sex);
// 如果希望在活动销毁的时候能够返回一个结果给上一个活动,就用startActivityForResult
startActivityForResult(intent, 1); // 请求码为1
}
// 在活动销毁后返回上一个活动的onActivityResult
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case 1:
if (resultCode == RESULT_OK){
int returnedData = data.getIntExtra("score", 0); // 默认为0
Toast.makeText(this, "您的测试分数为:" + returnedData, Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
}
}
批注:
public void startActivityForResult (Intent intent, int requestCode)
和打电话一样startActivityForResult(Intent, int, Bundle)
没有选择。
参数 | |
---|---|
intent |
Intent: 开始的意图。 |
requestCode |
int :如果>=0,则当活动退出时,此代码将在onActivityResult()中返回。 |
抛出 | |
---|---|
android.content.ActivityNotFoundException |
protected void onActivityResult (int requestCode, int resultCode, Intent data)
当您启动的活动退出时调用,为您提供requestCode,启动它,返回resultCode,以及来自它的任何其他数据。如果活动显式返回,则不会返回任何结果,或者在操作期间崩溃,resultCode将为RESULT_CANCELED。
当您的活动重新启动时,您将在onResume()之前立即收到此调用。
如果您的活动将noHistory设置为true,则永远不会调用此方法。
参数 | |
---|---|
requestCode |
int :最初提供给startActivityForResult()的整数请求代码,允许您识别此结果的来源。 |
resultCode |
int: 子活动通过其setResult()返回的整数结果代码。 |
data |
Intent :一个Intent,它可以将结果数据返回给调用者(各种数据可以附加到Intent“extras”)。 |
由于在一个活动中有可能调用startActivityForResult()方法去启动很多不同的活动,每一个活动返回的数据都会回调到onActivityResult()这个方法中,因此我们首先要做的就是通过resultCode的值来判断数据来源,确定这个是由哪一个活动返回的数据。
ResultActivity.java
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.TextView;
public class ResultActivity extends AppCompatActivity {
private TextView tv_sex;
private TextView tv_name;
private TextView tv_result;
private int score;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_result);
tv_name = (TextView) findViewById(R.id.tv_name);
tv_sex = (TextView) findViewById(R.id.tv_sex);
tv_result = (TextView) findViewById(R.id.tv_result);
// 获取MainActivity窜地过来的数据
Intent intent = getIntent();// 获取开启此activity的意图对象
// 获取name和sex的值
// 小技巧:传递的是什么数据类型,这边就按照传递的数据类型取
String name = intent.getStringExtra("name");
int sex = intent.getIntExtra("sex", 0);
// 根据name和sex显示数据
tv_name.setText(name);
byte[] bytes = null;
try {
// 显示性别
switch (sex) {
case 1:
tv_sex.setText("男");
bytes = name.getBytes("gbk");
break;
case 2:
tv_sex.setText("女");
bytes = name.getBytes("utf-8");
break;
case 3:
tv_sex.setText("人妖");
bytes = name.getBytes("iso8859-1");
break;
}
} catch (Exception e) {
e.printStackTrace();
}
int total = 0;
for (byte b : bytes) {
int number = b & 0xff;
total += number;
}
// 获取得分
score = Math.abs(total) % 100;
if (score > 90) {
tv_result.setText("你是世人的榜样!");
} else if (score > 80) {
tv_result.setText("你的人品不错..应该一表人才吧?");
} else if (score > 60) {
tv_result.setText("你有较好的人品..继续保持..");
} else if (score > 50) {
tv_result.setText("老实交待..那些论坛上面经常出现的偷拍照是不是你的杰作?");
} else if (score > 30) {
tv_result.setText("你的人品太差了。你应该有干坏事的嗜好吧?");
} else if (score > 20) {
tv_result.setText("杀过人没有?放过火没有?你应该无恶不做吧?");
} else if (score > 10) {
tv_result.setText("是我不好...不应该跟你谈人品问题的...");
} else {
tv_result.setText("不好意思,无法识别人品二字");
}
}
@Override
public void onBackPressed() {
Intent intent = new Intent();
intent.putExtra("score", score);
setResult(RESULT_OK, intent);
finish();
}
}
批注:
当用户按下Back后退键,就回去执行onBackPressed()方法中的代码,我们重写这个方法再添加逻辑就行了。
这个activity接着在Manifest中添加<activity android:name=".ResultActivity" />就行了
activity_result.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="张三"/>
<TextView
android:id="@+id/tv_sex"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="男"/>
<TextView
android:id="@+id/tv_result"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="人品好"/>
</LinearLayout>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:hint="请输入姓名"/>
<RadioGroup
android:id="@+id/radioGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rb_male"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="男" />
<RadioButton
android:id="@+id/rb_female"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="女" />
<RadioButton
android:id="@+id/rb_other"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="人妖" />
</RadioGroup>
<Button
android:onClick="click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="计算"/>
</LinearLayout>
===========================Talk is cheap, show me the code===========================