美文网首页
Android Training(四):使用 Intent 与其

Android Training(四):使用 Intent 与其

作者: Marker_Sky | 来源:发表于2018-03-13 15:05 被阅读0次

一. Getting Started

1.5 Interacting with Other Apps

Android 应用一般具有若干个Activity。每个 Activity 显示一个用户界面,用户可通过该界面执行特定任务(比如,查看地图或拍照)。要将用户从一个 Activity 转至另一 Activity,您的应用必须使用 Intent 定义您的应用做某事的 “Intent”。

1.5.1 Sending the User to Another App

构建隐式 Intent


  • 使用指定电话号码的 Uri 数据创建发起电话呼叫的 Intent:
Uri number = Uri.parse("tel:5551234");
Intent callIntent = new Intent(Intent.ACTION_DIAL, number);
  • 查看地图:
// Map point based on address
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
// Or map point based on latitude/longitude
// Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z param is zoom level
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
  • 查看网页:
Uri webpage = Uri.parse("http://www.android.com");
Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);
  • 发送带附件的电子邮件:
Intent emailIntent = new Intent(Intent.ACTION_SEND);
// The intent does not have a URI, so declare the "text/plain" MIME type
emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jon@example.com"}); // recipients
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");
emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text");
emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"));
// You can also attach multiple items by passing an ArrayList of Uris
  • 创建日历事件:
Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI);
Calendar beginTime = Calendar.getInstance().set(2012, 0, 19, 7, 30);
Calendar endTime = Calendar.getInstance().set(2012, 0, 19, 10, 30);
calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis());
calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis());
calendarIntent.putExtra(Events.TITLE, "Ninja class");
calendarIntent.putExtra(Events.EVENT_LOCATION, "Secret dojo");

注:只有 API 级别 14 或更高级别支持此日历事件 Intent。

验证是否存在接收 Intent 的应用


调用 queryIntentActivities() 来获取是否有能处理该 Intent 的 Activity 列表。如果返回的 List 不为空,可以安全使用该 Intent。

PackageManager packageManager = getPackageManager();
List activities = packageManager.queryIntentActivities(intent,
        PackageManager.MATCH_DEFAULT_ONLY);
boolean isIntentSafe = activities.size() > 0;

启动具有 Intent 的 Activity

此处显示完整的示例:如何创建查看地图的 Intent,验证是否存在处理 Intent 的应用,然后启动它:

// Build the intent
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);

// Verify it resolves
PackageManager packageManager = getPackageManager();
List<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);
boolean isIntentSafe = activities.size() > 0;

// Start an activity if it's safe
if (isIntentSafe) {
    startActivity(mapIntent);
}

显示应用选择器


Intent intent = new Intent(Intent.ACTION_SEND);
...

// Always use string resources for UI text.
// This says something like "Share this photo with"
String title = getResources().getString(R.string.chooser_title);
// Create intent to show chooser
Intent chooser = Intent.createChooser(intent, title);

// Verify the intent will resolve to at least one activity
if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(chooser);
}

1.5.2 startActivityForResult

启动 Activity


例如,此处显示如何开始允许用户选择联系人的 Activity:

static final int PICK_CONTACT_REQUEST = 1;  // The request code
...
private void pickContact() {
    Intent pickContactIntent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts"));
    pickContactIntent.setType(Phone.CONTENT_TYPE); // Show user only contacts w/ phone numbers
    startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST);
}

接收结果


Activity 返回结果时会调用 onActivityResult() 方法,该方法有三个参数:

  • requestCode:请求码,作为标记;
  • resultCode:结果码,如果操作成功返回 RESULT_OK,失败则 RESULT_CANCELED
  • data:传送数据的 Intent 对象。

本例说明您可以如何处理“选择联系人” Intent 的结果。

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // Check which request we're responding to
    if (requestCode == PICK_CONTACT_REQUEST) {
        // Make sure the request was successful
        if (resultCode == RESULT_OK) {
            // The user picked a contact.
            // The Intent's data Uri identifies which contact was selected.

            // Do something with the contact here (bigger example below)
        }
    }
}

成功获取联系人数据后的进一步操作:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // Check which request it is that we're responding to
    if (requestCode == PICK_CONTACT_REQUEST) {
        // Make sure the request was successful
        if (resultCode == RESULT_OK) {
            // Get the URI that points to the selected contact
            Uri contactUri = data.getData();
            // We only need the NUMBER column, because there will be only one row in the result
            String[] projection = {Phone.NUMBER};

            // Perform the query on the contact to get the NUMBER column
            // We don't need a selection or sort order (there's only one result for the given URI)
            // CAUTION: The query() method should be called from a separate thread to avoid blocking
            // your app's UI thread. (For simplicity of the sample, this code doesn't do that.)
            // Consider using CursorLoader to perform the query.
            Cursor cursor = getContentResolver()
                    .query(contactUri, projection, null, null, null);
            cursor.moveToFirst();

            // Retrieve the phone number from the NUMBER column
            int column = cursor.getColumnIndex(Phone.NUMBER);
            String number = cursor.getString(column);

            // Do something with the phone number...
        }
    }
}

注意读取联系人需要申请相应权限

1.5.2 Allowing Other Apps to Start Your Activity

要允许其他应用启动您的 Activity,您需要在清单文件中为对应的 <activity> 元素添加一个 <intent-filter> 元素。

当您的应用安装在设备上时,系统会识别您的 Intent 过滤器并添加信息至所有已安装应用支持的 Intent 内部目录。当应用通过隐含 Intent 调用 startActivity()startActivityForResult() 时,系统会找到可以响应该 Intent 的 Activity。

添加 Intent 过滤器


Activity 基本 Intent 过滤器:

  • 操作 <action> 标签:表示要执行的操作名,如 ACTION_SENDACTION_VIEW
  • 数据 <data> 标签:与 Intent 关联的数据描述。可以指定 MIME 类型、URI 前缀、URI 架构或这些的组合以及其他指示所接受数据类型的项。

:如果您无需声明关于数据的具体信息 Uri 比如,您的 Activity 处理其他类型的“额外”数据而不是 URI 时),您应只指定 android:mimeType 属性声明您的 Activity 处理的数据类型,比如 text/plainimage/jpeg

  • 类别:<category> 标签:提供另外一种表征处理 Intent 的 Activity 的方法,通常与用户手势或 Activity 启动的位置有关。 经常使用默认的 CATEGORY_DEFAULT 进行定义。

声明 Activity 的 Intent 过滤器的各项属性,比如下方的一个接收收据类型为文本或图像时启动的 Activity:

<activity android:name="ShareActivity">
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
        <data android:mimeType="image/*"/>
    </intent-filter>
</activity>

如果某 Activity 想要支持两种不同的隐式 Intent 调用,需要再配置一个 Intent-filter 过滤器。

<activity android:name="ShareActivity">
    <!-- filter for sending text; accepts SENDTO action with sms URI schemes -->
    <intent-filter>
        <action android:name="android.intent.action.SENDTO"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:scheme="sms" />
        <data android:scheme="smsto" />
    </intent-filter>
    <!-- filter for sending text or images; accepts SEND action and text or image data -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
</activity>

:为了接收隐含 Intent,您必须在 Intent 过滤器中包含 CATEGORY_DEFAULT 类别。方法 startActivity()startActivityForResult() 将按照已声明 CATEGORY_DEFAULT 类别的方式处理所有 Intent。如果您不在 Intent 过滤器中声明它,则没有隐含 Intent 分解为您的 Activity。

处理您的 Activity 中的 Intent


在 onCreate() 中获取传递来的 Intent 信息。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    // Get the intent that started this activity
    Intent intent = getIntent();
    Uri data = intent.getData();

    // Figure out what to do based on the intent type
    if (intent.getType().indexOf("image/") != -1) {
        // Handle intents with image data ...
    } else if (intent.getType().equals("text/plain")) {
        // Handle intents with text ...
    }
}

返回结果


使用 setResult() 方法和要返回的 Intent 对象来指定代码和结果。

// Create intent to deliver some kind of result data
Intent result = new Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri"));
setResult(Activity.RESULT_OK, result);
finish();

:默认情况下,结果设置为 RESULT_CANCELED。因此,如果用户在完成操作动作或设置结果之前按了返回按钮,原始 Activity 会收到“已取消”的结果。

如果只需要返回某个整数,可以使用以下方法:

setResult(RESULT_COLOR_RED);
finish();

1.6 Working with System Permissions

请求需要的权限


// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
                Manifest.permission.READ_CONTACTS)
        != PackageManager.PERMISSION_GRANTED) {

    // Should we show an explanation?
    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
            Manifest.permission.READ_CONTACTS)) {

        // Show an expanation to the user *asynchronously* -- don't block
        // this thread waiting for the user's response! After the user
        // sees the explanation, try again to request the permission.

    } else {

        // No explanation needed, we can request the permission.

        ActivityCompat.requestPermissions(thisActivity,
                new String[]{Manifest.permission.READ_CONTACTS},
                MY_PERMISSIONS_REQUEST_READ_CONTACTS);

        // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
        // app-defined int constant. The callback method gets the
        // result of the request.
    }
}

处理权限请求响应


@Override
public void onRequestPermissionsResult(int requestCode,
        String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay! Do the
                // contacts-related task you need to do.

            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request
    }
}

在此分享一种权限申请写法:

  1. 首先定义一个权限申请成功或失败的回调接口:
private interface PermissionCallback
{
    void onSuccess();
    void onFailure();
}
  1. 下面代码以申请摄像机权限举例,如果需要申请更多权限除了要在 manifest 文件中添加,也需要在 String[] 字符串数组中添加:
@TargetApi(23)
private void requestCameraPermission(PermissionCallback callback)
{
    if (Build.VERSION.SDK_INT >= 23) {
        if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            int requestCode = permissionRequestCodeSerial;
            permissionRequestCodeSerial += 1;
            permissionCallbacks.put(requestCode, callback);
            requestPermissions(new String[]{Manifest.permission.CAMERA}, requestCode);
        } else {
            callback.onSuccess();
        }
    } else {
        callback.onSuccess();
    }
}
  1. 权限申请回调,同时回调自定义接口:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
{
    if (permissionCallbacks.containsKey(requestCode)) {
        PermissionCallback callback = permissionCallbacks.get(requestCode);
        permissionCallbacks.remove(requestCode);
        boolean executed = false;
        for (int result : grantResults) {
            if (result != PackageManager.PERMISSION_GRANTED) {
                executed = true;
                callback.onFailure();
            }
        }
        if (!executed) {
            callback.onSuccess();
        }
    }
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
  1. 使用时在相关 Activity 或 app 初始化时调用第 2 步中的方法:
requestCameraPermission(new PermissionCallback() {
    @Override
    public void onSuccess() {
    }

    @Override
    public void onFailure() {
    }
});

相关文章

网友评论

      本文标题:Android Training(四):使用 Intent 与其

      本文链接:https://www.haomeiwen.com/subject/iesozxtx.html