检查 Intent.ACTION_VIEW 上的用户操作

Posted

技术标签:

【中文标题】检查 Intent.ACTION_VIEW 上的用户操作【英文标题】:Check user action on Intent.ACTION_VIEW 【发布时间】:2012-09-26 11:47:48 【问题描述】:

我有一个包含一些文件的列表视图,可以有各种类型,例如 pdf 或文档。当用户单击一个时,我会获取文件 mime 类型并启动一个意图,让用户选择使用哪个应用程序来打开它文件。我想知道的是用户选择了一些东西,或者只是按下并没有选择任何东西。 到目前为止我尝试的是执行 startActivityForResult 并检查是否成功,但它总是返回 RESULT_CANCELED

    static final int SELECTED_VIEWER = 1;

    Intent intent = new Intent(Intent.ACTION_VIEW);     
    intent.setDataAndType(Uri.parse(filePath), mimetype);
    try 
        startActivityForResult(intent, SELECTED_VIEWER);
    catch (ActivityNotFoundException e) 
        Toast.makeText(getActivity(), 
           Strings.ERROR_NO_VIEWER, 
            Toast.LENGTH_SHORT).show();
    

    public void onActivityResult(int requestCode, int resultCode, Intent data) 
     if (requestCode == SELECTED_VIEWER) 
         if (resultCode == Activity.RESULT_CANCELED ) 
             //do something
         
     
 

我什至尝试使用 startActivityForResult(Intent.createChooser 但仍然无济于事。 我如何知道用户是否选择了该列表中的某些内容,或者他是否取消了打开?

【问题讨论】:

【参考方案1】:

正如 android 开发者在 Activities 上所写的那样

在其他协议中(例如 ACTION_MAIN 或 ACTION_VIEW),您可能无法获得预期的结果。

你不能指望动作视图返回你所期望的,所以我所做的是实现一个自定义警报对话框,显示可以打开某个文件的所有可能的应用程序,一个稍微修改的版本,如下所示Custom intent chooser

为那些想知道的人编写代码,它以 filePath 作为参数,并向您显示所有已安装的应用程序,这些应用程序可以通过获取 mimetype 来处理该文件类型。与完整路径一起使用。可以使用

调用
AlertDialogIntentChooser alertDialog = new  AlertDialogIntentChooser(filePath,getActivity());
alertDialog.show();

这是一个类,它可以接受一个可选的委托以及活动回调

public class AlertDialogIntentChooser 
private String filePath;
private Activity activity;
private AlertDialog dialog;
private AlertDialogDelegate delegate;
private ListItem[] items;

public AlertDialogIntentChooser(String filePath,Activity activity)
    this.filePath = filePath;
    this.activity = activity;
    init();


public void setDialogDelegate(AlertDialogDelegate delegate)
    this.delegate = delegate;


private void init()

    initApplicationItems();

    AlertDialog.Builder builder = new AlertDialog.Builder(activity);
    builder.setTitle(Strings.STRING_SELECT_APPLICATION);
    builder.setIcon(R.drawable.ic_share);

    builder.setOnCancelListener(new OnCancelListener() 

        @Override
        public void onCancel(DialogInterface paramDialogInterface) 
            if(delegate!=null)
                delegate.onDialogCancelled(paramDialogInterface);
        
    );

    builder.setAdapter(adapter, new DialogInterface.OnClickListener() 
        @Override
        public void onClick(DialogInterface dialog, int which)          

            Intent intentPdf = new Intent(Intent.ACTION_VIEW);
            MimeTypeMap myMime = MimeTypeMap.getSingleton();
            String fileExt = MimeTypeMap.getFileExtensionFromUrl(Uri.parse(filePath));
            String mimeType = myMime.getMimeTypeFromExtension(fileExt);                 
            intentPdf.setClassName(items[which].context, items[which].packageClassName);
            intentPdf.setDataAndType(Uri.parse(filePath), mimeType);
            try 
                activity.startActivity(intentPdf);
                dialog.dismiss();
                if(delegate!=null)
                    delegate.onItemSelected(items[which].context, items[which].packageClassName);
            catch (ActivityNotFoundException e) 
                Toast.makeText(activity, 
                        Strings.ERROR_NO_VIEWER, 
                        Toast.LENGTH_SHORT).show();
                dialog.dismiss();
                           
        
    );

    dialog = builder.create();        


private void initApplicationItems()
    Intent intentPdf = new Intent(Intent.ACTION_VIEW);

    MimeTypeMap myMime = MimeTypeMap.getSingleton();
    String fileExt = MimeTypeMap.getFileExtensionFromUrl(Uri.parse(filePath));
    String mimeType = myMime.getMimeTypeFromExtension(fileExt);             
    intentPdf.setDataAndType(Uri.parse(filePath), mimeType);
    PackageManager pm = activity.getPackageManager();
    List<ResolveInfo> resInfos = pm.queryIntentActivities(intentPdf, 0);

    items = new ListItem[resInfos.size()];
    int i = 0;
    for (ResolveInfo resInfo : resInfos) 
        String context = resInfo.activityInfo.packageName;
        String packageClassName = resInfo.activityInfo.name;
        CharSequence label = resInfo.loadLabel(pm);
        Drawable icon = resInfo.loadIcon(pm);
        items[i] = new ListItem(label.toString(), icon, context, packageClassName);
        ++i;
    


public void show()
    dialog.show();


private ListAdapter adapter = new ArrayAdapter<ListItem>(
          activity,
    android.R.layout.select_dialog_item,
    android.R.id.text1,
    items)

    public View getView(int position, View convertView, ViewGroup parent) 

        View v = super.getView(position, convertView, parent);
        TextView tv = (TextView)v.findViewById(android.R.id.text1);

        int dpS = (int) (72 * activity.getResources().getDisplayMetrics().density *  0.5f);
        items[position].icon.setBounds(0, 0, dpS, dpS);
        tv.setCompoundDrawables(items[position].icon, null, null, null);

        int dp5 = (int) (5 * activity.getResources().getDisplayMetrics().density *  0.5f);
        tv.setCompoundDrawablePadding(dp5);

        return v;
    
;

class ListItem 
     public final String name;
     public final Drawable icon;
     public final String context;
     public final String packageClassName;

     public ListItem(String text, Drawable icon, String context, String packageClassName) 
         this.name = text;
         this.icon = icon;
         this.context = context;
         this.packageClassName = packageClassName;
     

     @Override
     public String toString() 
         return name;
     
 

 public static interface AlertDialogDelegate
     public void onDialogCancelled(DialogInterface paramDialogInterface);
     public void onItemSelected(String packageName, String className);
 

【讨论】:

【参考方案2】:

试试

如果 (resultCode == RESULT_CANCELED) 而不是 if (resultCode == Activity.RESULT_CANCELED )

【讨论】:

【参考方案3】:

试试这个..

Intent intent = new Intent(Intent.ACTION_VIEW);     
        intent.setDataAndType(Uri.parse(filePath),mimetype);
        startActivity(intent);

【讨论】:

我需要知道用户是点击了什么,还是关闭了对话框

以上是关于检查 Intent.ACTION_VIEW 上的用户操作的主要内容,如果未能解决你的问题,请参考以下文章

Intent.ACTION_VIEW

Intent

Twitter上的Android分享

安卓中一句代码,解决拨号,定位,网页,卸载,安装,播放,邮件,短信

用户ACTION_VIEW在APP中打开URL的意图。

Android中的Uri.parse()