documentsUI下载列表点击事件流程

解析Android文档处理流程及多模式展示
本文详细解析了Android中文档处理流程,包括列表布局、目录切换、事件处理等关键步骤,并深入探讨了不同模式下(列表模式、网格模式)的适配策略。通过分析DocumentsActivity、DocumentsAdapter等关键组件,展示了如何根据文档类型和用户操作选择合适的展示方式,最终实现高效、灵活的文档管理与交互体验。

1.列表布局文件item_doc_list.xml

2.DirectoryFragment.java

private class DocumentsAdapter extends BaseAdapter { 

private View getDocumentView(){

.......

if (state.derivedMode == MODE_LIST) {
                    convertView = inflater.inflate(R.layout.item_doc_list, parent, false);
                } else if (state.derivedMode == MODE_GRID) {
                    convertView = inflater.inflate(R.layout.item_doc_grid, parent, false);}

.....

}

}

mListView.setAdapter(mAdapter);

public View onCreateView(){

mListView.setOnItemClickListener(mItemListener);

}

private OnItemClickListener mItemListener = new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            final Cursor cursor = mAdapter.getItem(position);
Log.e("like","OnItemClickListener position="+position);
            if (cursor != null) {
                final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
                final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
Log.e("like","docMimeType="+docMimeType+" docFlags="+docFlags);
                if (isDocumentEnabled(docMimeType, docFlags)) {
                    final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor);
Log.e("like","OnItemClickListener doc.displayName ="+doc.displayName);
                    ((DocumentsActivity) getActivity()).onDocumentPicked(doc);
                }
            }
        }
    };


3.DocumentsActivity.java 来处理事件

public void onDocumentPicked(DocumentInfo doc) {
        final FragmentManager fm = getFragmentManager();
Log.e("like","onDocumentPicked doc.displayName ="+doc.displayName+"   mState.action ="+mState.action);
        if (doc.isDirectory()) {
            mState.stack.push(doc);
            mState.stackTouched = true;
            onCurrentDirectoryChanged(ANIM_DOWN);
        } else if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
            // Explicit file picked, return
            new ExistingFinishTask(doc.derivedUri).executeOnExecutor(getCurrentExecutor());
        } else if (mState.action == ACTION_CREATE) {
            // Replace selected file
            SaveFragment.get(fm).setReplaceTarget(doc);
        } else if (mState.action == ACTION_MANAGE) {
            // First try managing the document; we expect manager to filter
            // based on authority, so we don't grant.
            final Intent manage = new Intent(DocumentsContract.ACTION_MANAGE_DOCUMENT);
            manage.setData(doc.derivedUri);
            try {
                startActivity(manage);
Log.e("like","ACTION_MANAGE"+"  doc.derivedUri ="+doc.derivedUri);

//doc.derivedUri =content://com.android.providers.downloads.documents/document/2
            } catch (ActivityNotFoundException ex) {
                // Fall back to viewing
                final Intent view = new Intent(Intent.ACTION_VIEW);
                view.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                view.setData(doc.derivedUri);
                try {
Log.e("like","doc.derivedUri ="+doc.derivedUri+"ex = "+ex);
                    startActivity(view);
                } catch (ActivityNotFoundException ex2) {
                    /// M: Show toast with enhance way.
                    showToast(R.string.toast_no_application);
                }
            }
        }
    }

3.在packages\providers\DownloadProvider\ui\AndroidManifest.xml

<activity
            android:name=".TrampolineActivity"
            android:theme="@android:style/Theme.NoDisplay"
            android:permission="android.permission.MANAGE_DOCUMENTS">
            <intent-filter>
                <action android:name="android.provider.action.MANAGE_DOCUMENT" />
                <category android:name="android.intent.category.DEFAULT" />
                <data
                    android:scheme="content"
                    android:host="com.android.providers.downloads.documents"
                    android:mimeType="*/*" />
            </intent-filter>
        </activity>


4.TrampolineActivity.java

@Override
    protected void onCreate(Bundle savedInstanceState) {

switch (status) {
            case DownloadManager.STATUS_PENDING:
            case DownloadManager.STATUS_RUNNING:
Log.d("like", "1");
                sendRunningDownloadClickedBroadcast(id);
                finish();
                break;


            case DownloadManager.STATUS_PAUSED:
Log.d("like", "2");
                if (reason == DownloadManager.PAUSED_QUEUED_FOR_WIFI) {
                    PausedDialogFragment.show(getFragmentManager(), id);
                } else {
                    sendRunningDownloadClickedBroadcast(id);
                    finish();
                }
                break;


            case DownloadManager.STATUS_SUCCESSFUL:
Log.d("like", "startViewIntent id = "+id);
                if (!OpenHelper.startViewIntent(this, id, 0)) {
                    Toast.makeText(this, R.string.download_no_application_title, Toast.LENGTH_SHORT)
                            .show();
                }
                finish();
                break;


            case DownloadManager.STATUS_FAILED:
Log.d("like", "4");
Log.e("like","DownloadManager.STATUS_FAILED");
                FailedDialogFragment.show(getFragmentManager(), id, reason);
                break;
        }

}


5.执行到OpenHelper.startViewIntent(this, id, 0) OpenHelper.java  通过setDataAndType来打开对应应用


public static boolean startViewIntent(Context context, long id, int intentFlags) {
        final Intent intent = OpenHelper.buildViewIntent(context, id);
        if (intent == null) {
            Log.w(TAG, "No intent built for " + id);
            return false;
        }


        intent.addFlags(intentFlags);
        try {
            context.startActivity(intent);
            return true;
        } catch (ActivityNotFoundException e) {
            Log.w(TAG, "Failed to start " + intent + ": " + e);
            return false;
        }
    }


    /**
     * Build an {@link Intent} to view the download with given ID, handling
     * subtleties around installing packages.
     */
    private static Intent buildViewIntent(Context context, long id) {
        final DownloadManager downManager = (DownloadManager) context.getSystemService(
                Context.DOWNLOAD_SERVICE);
        downManager.setAccessAllDownloads(true);


        final Cursor cursor = downManager.query(new DownloadManager.Query().setFilterById(id));
        try {
            if (!cursor.moveToFirst()) {
                return null;
            }


            final Uri localUri = getCursorUri(cursor, COLUMN_LOCAL_URI);
     
            // ckt: HePJ changed for bug 1065 @{
            if(null == localUri){
                return null;
            }
            /// @}


            final File file = getCursorFile(cursor, COLUMN_LOCAL_FILENAME);
            String mimeType = getCursorString(cursor, COLUMN_MEDIA_TYPE);
            if (mimeType == null && file.getName().endsWith(".vcf")) {
                mimeType = "text/x-vcard";
            }
            Log.d(TAG, "file: " + file.getName() + " mimeType: " + mimeType);


            final Intent intent = new Intent(Intent.ACTION_VIEW);


            /// M: Add to support MTK DRM @{
            if (Constants.MTK_DRM_ENABLED
                    && null != mimeType
                    && (mimeType.equalsIgnoreCase(OmaDrmStore.DrmObjectMime.MIME_DRM_MESSAGE) || mimeType
                            .equalsIgnoreCase(OmaDrmStore.DrmObjectMime.MIME_DRM_CONTENT))) {
                Xlog.i(Constants.DL_DRM, "will send DRM intent");
                //DrmManagerClient drmClient = new DrmManagerClient(context);
                //OmaDrmClient drmClient = new OmaDrmClient(context);
                mimeType = DownloadDrmHelper.getOriginalMimeType(context, file, mimeType);


                Xlog.d(Constants.DL_DRM, "Open DRM file:" + localUri + " MimeType is" + mimeType);
                intent.setDataAndType(localUri, mimeType);
            } else {
            /// @}
            if ("application/vnd.android.package-archive".equals(mimeType)) {
                // PackageInstaller doesn't like content URIs, so open file
                intent.setDataAndType(localUri, mimeType);


                // Also splice in details about where it came from
                final Uri remoteUri = getCursorUri(cursor, COLUMN_URI);
                intent.putExtra(Intent.EXTRA_ORIGINATING_URI, remoteUri);
                intent.putExtra(Intent.EXTRA_REFERRER, getRefererUri(context, id));
                intent.putExtra(Intent.EXTRA_ORIGINATING_UID, getOriginatingUid(context, id));
            } else if ("file".equals(localUri.getScheme())) {
                intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
                        | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                intent.setDataAndType(
                        ContentUris.withAppendedId(ALL_DOWNLOADS_CONTENT_URI, id), mimeType);
            } else {
                intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                intent.setDataAndType(localUri, mimeType);
            }
            /// M: Add to support MTK DRM @{
            }
            /// @}
            return intent;
        } finally {
            cursor.close();
        }
    }



``` 04-01 09:55:21.762 1410 3320 E ActivityTaskManager: Without BAL hardening this activity start would be allowed! [callingPackage: com.google.android.documentsui; callingUid: 10045; appSwitchState: 2; callingUidHasAnyVisibleWindow: false; callingUidProcState: NONEXISTENT; isCallingUidPersistentSystemProcess: false; balAllowedByPiSender: BackgroundStartPrivileges[allowsBackgroundActivityStarts=false, allowsBackgroundForegroundServiceStarts=true, originatingToken=null]; realCallingPackage: com.android.launcher3; realCallingUid: 10127; realCallingUidHasAnyVisibleWindow: true; realCallingUidProcState: TOP; isRealCallingUidPersistentSystemProcess: false; originatingPendingIntent: null; backgroundStartPrivileges: BackgroundStartPrivileges[allowsBackgroundActivityStarts=false, allowsBackgroundForegroundServiceStarts=false, originatingToken=null]; intent: Intent { dat= flg=0x10380000 cmp=com.google.android.documentsui/com.android.documentsui.files.FilesActivity }; callerApp: null; inVisibleTask: false] 04-01 09:55:21.762 1410 3320 W ActivityTaskManager: Background activity launch blocked [callingPackage: com.google.android.documentsui; callingUid: 10045; appSwitchState: 2; callingUidHasAnyVisibleWindow: false; callingUidProcState: NONEXISTENT; isCallingUidPersistentSystemProcess: false; balAllowedByPiSender: BackgroundStartPrivileges[allowsBackgroundActivityStarts=false, allowsBackgroundForegroundServiceStarts=true, originatingToken=null]; realCallingPackage: com.android.launcher3; realCallingUid: 10127; realCallingUidHasAnyVisibleWindow: true; realCallingUidProcState: TOP; isRealCallingUidPersistentSystemProcess: false; originatingPendingIntent: null; backgroundStartPrivileges: BackgroundStartPrivileges[allowsBackgroundActivityStarts=false, allowsBackgroundForegroundServiceStarts=false, originatingToken=null]; intent: Intent { dat= flg=0x10380000 cmp=com.google.android.documentsui/com.android.documentsui.files.FilesActivity }; callerApp: null; inVisibleTask: false] 04-01 09:55:21.767 1410 3320 E ActivityTaskManager: Abort background activity starts from 10045 04-01 09:55:21.768 1410 3320 I ActivityTaskManager: START u0 {dat= flg=0x10380000 cmp=com.google.android.documentsui/com.android.documentsui.files.FilesActivity} with LAUNCH_MULTIPLE from uid 10045 (realCallingUid=10127) (BAL_BLOCK) result code=102```重启后在recent启动files失败,为什么 可以从recent源码中修改吗?或者是从files源码中修改?为什么会出现这样的问题?触发条件时什么?
04-02
### 关于 Android DocumentsUI 文档及相关示例 对于寻找有关 Android `DocumentsUI` 的文档和实例的需求,官方资源提供了详尽的信息。然而,有时访问在线资料可能遇到困难。针对这一情况,可以考虑获取离线版的 Android 开发文档。 #### 获取离线开发文档 为了更便捷地查阅文档而不受网络状况影响,建议下载适用于 Windows 平台的 CHM (Compiled HTML Help) 格式的 Android 5.0 开发者指南[^2]。此版本不仅涵盖了 API 参考手册还包含了完整的教程和其他有用的内容。需要注意的是,在打开这些文件之前应该先解除它们的安全锁定状态以确保正常浏览功能。 #### 查找具体模块文档 尽管上述提到的是较旧版本的操作系统级别的文档集,但对于特定组件如 `DocumentsUI` ,最权威的消息源仍然是最新的 Android 官方网站上的说明页面以及 GitHub 上对应的开源项目仓库中的 README 和其他 markdown 文件。如果希望获得更加针对性的帮助或者样例代码片段,则可以通过搜索引擎加上站点限定符来定位相关内容;例如:“site:developer.android.com documentsui”。 #### 使用 Gradle 进行依赖管理 当涉及到实际项目的构建时,合理配置 build.gradle 文件内的插件与工具链版本同样重要。这有助于保持环境稳定并减少潜在兼容性问题的发生几率[^1]。 ```groovy plugins { id 'com.android.application' version '7.4.2' apply false } android { compileSdkVersion 33 defaultConfig { minSdkVersion 21 targetSdkVersion 33 } } ``` 以上展示了如何指定一个较为现代的 SDK 编译目标,并引入了最新发布的应用插件作为例子。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值