记录下Intent.resolveActivity

本文详细介绍了在Android开发中如何使用Intent调用第三方应用的Activity或Service,并提供了检查Intent是否可被解析的方法,避免因目标应用未安装导致的异常。

详解1:

在自己的应用程序中利用第三方应用程序的Activity和Service是十分方便的,但是你无法保证用户设备上安装了特定的某个应用软件,或者设备上有能够处理你的Intent请求的程序。

 因此,在启动第三方APK里的Activity之前,确定调用是否可以解析为一个Activity是一种很好的做法。

通过Intent的resolveActivity方法,并想该方法传入包管理器可以对包管理器进行查询以确定是否有Activity能够启动该Intent:

[java] view plain copy

  1. // Create the impliciy Intent to use to start a new Activity.  
  2. Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:555-2368"));  
  3. // Check if an Activity exists to perform this action.  
  4. PackageManager pm = context.getPackageManager();  
  5. ComponentName cn = intent.resolveActivity(pm);  
  6. if (cn == null) {  
  7.     // If there is no Activity available to perform the action  
  8.     // Check to see if the Google Play Store is available.  
  9.     Uri marketUri = Uri.parse("market://search?q=pname:com.myapp.packagename");  
  10.     Intent marketIntent = new Intent(Intent.ACTION_VIEW).setData(marketUri);  
  11.     // If the Google Play Store is available, use it to download an application  
  12.     // capable of performing the required action. Otherwise log an error.  
  13.     if (marketIntent.resolveActivity(pm) != null) {  
  14.         context.startActivity(marketIntent);  
  15.     } else {  
  16.         Log.d(TAG, "Market client not available.");  
  17.     }  
  18. } else{  
  19.     context.startActivity(intent);  
  20. ------------------------------------------------------------------------------------------------------------------------------------

    2”

    类似打开相机,发送图片等隐式Intent,是并不一定能够在所有的Android设备上都正常运行。例如打开相机的隐式Intent,如果系统相机应用被关闭或者不存在相机应用,又或者是相机应用的某些权限被关闭等等情况都可能导致这个隐式的Intent无法正常工作。一旦发生隐式Intent找不到合适的调用组件的情况,系统就会抛出ActivityNotFoundException的异常,如果我们的应用没有对这个异常做任何处理,那应用就会发生Crash。

    预防这个问题的最佳解决方案是在发出这个隐式Intent之前调用resolveActivity做检查,关于这个API的解释以及用法如下:

  21. 然后这个API的使用范例如下:

  22. Intent intent = new Intent(Intent.ACTION_XXX);
    ComponentName componentName = intent.resolveActivity(getPackageManager());
    if(componentName != null) {
    String className = componentName.getClassName();
    }
     

/** * Return the Activity component that should be used to handle this intent. * The appropriate component is determined based on the information in the * intent, evaluated as follows: * * <p>If {@link #getComponent} returns an explicit class, that is returned * without any further consideration. * * <p>The activity must handle the {@link Intent#CATEGORY_DEFAULT} Intent * category to be considered. * * <p>If {@link #getAction} is non-NULL, the activity must handle this * action. * * <p>If {@link #resolveType} returns non-NULL, the activity must handle * this type. * * <p>If {@link #addCategory} has added any categories, the activity must * handle ALL of the categories specified. * * <p>If {@link #getPackage} is non-NULL, only activity components in * that application package will be considered. * * <p>If there are no activities that satisfy all of these conditions, a * null string is returned. * * <p>If multiple activities are found to satisfy the intent, the one with * the highest priority will be used. If there are multiple activities * with the same priority, the system will either pick the best activity * based on user preference, or resolve to a system class that will allow * the user to pick an activity and forward from there. * * <p>This method is implemented simply by calling * {@link PackageManager#resolveActivity} with the "defaultOnly" parameter * true.</p> * <p> This API is called for you as part of starting an activity from an * intent. You do not normally need to call it yourself.</p> * * @param pm The package manager with which to resolve the Intent. * * @return Name of the component implementing an activity that can * display the intent. * * @see #setComponent * @see #getComponent * @see #resolveActivityInfo */ public ComponentName resolveActivity(@NonNull PackageManager pm) { if (mComponent != null) { return mComponent; } ResolveInfo info = pm.resolveActivity( this, PackageManager.MATCH_DEFAULT_ONLY); if (info != null) { Slog.d("qjx","info = "+info.activityInfo.packageName+" , this = "+this); return new ComponentName( info.activityInfo.applicationInfo.packageName, info.activityInfo.name); } return null; } 系统中是这个吗
12-10
package com.shhg; import android.app.Activity; import android.app.AlertDialog; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; public class MainActivity extends Activity { private EditText urlInput; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 显示视频播放对话框 showVideoDialog(); } /** * 显示视频播放对话框 */ private void showVideoDialog() { View dialogView = View.inflate(this, R.layout.dialog_video, null); urlInput = dialogView.findViewById(R.id.et_url); Button playButton = dialogView.findViewById(R.id.btn_play); AlertDialog dialog = new AlertDialog.Builder(this) .setTitle("视频播放器") .setView(dialogView) .setCancelable(true) .create(); // 设置点击事件 playButton.setOnClickListener(v -> handlePlayButtonClick(dialog)); dialog.show(); } /** * 处理播放按钮点击事件 */ private void handlePlayButtonClick(AlertDialog dialog) { String videoUrl = urlInput.getText().toString().trim(); if (videoUrl.isEmpty()) { urlInput.setError("请输入视频URL"); return; } if (isValidUrl(videoUrl)) { playVideo(videoUrl); dialog.dismiss(); } else { showErrorMessage("无效URL", "请输入有效的视频链接"); } } /** * 播放视频 */ private void playVideo(String videoUrl) { try { Uri uri = Uri.parse(videoUrl); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(uri, "video/*"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } else { showErrorMessage("错误", "未找到可用的视频播放器"); } } catch (Exception e) { showErrorMessage("无效URL", "请输入有效的视频链接\n错误信息: " + e.getMessage()); } } /** * 验证URL是否合法 */ private boolean isValidUrl(String url) { return url.startsWith("http://") || url.startsWith("https://"); } /** * 显示错误提示对话框 */ private void showErrorMessage(String title, String message) { new AlertDialog.Builder(this) .setTitle(title) .setMessage(message) .setPositiveButton("确定", null) .show(); } } 帮我修复一下
07-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值