我希望用户能够在手机中选择任何文件类型,然后使用意图再次查看。
选择文件项我写这个(我使用Kotlin,Java中的同样问题):
fun goToDocumentPicker() {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "*/*"
if (intent.resolveActivity(mContext.packageManager) != null)
mContext.startActivityForResult(intent, REQUEST_DOCUMENT)
}
并显示所选项目:
fun showDocumentPreviewer(uri: Uri) {
val i = Intent(Intent.ACTION_VIEW)
i.data = uri
mContext.startActivity(i)
}
文档选择器工作正常,在onActivityResult
我可以接收所选文档的Uri对象,但文档预览器无法打开该对象。已经尝试将mime-type设置为预览器的意图但不成功。我在Android中使用不正确的方式打开文件了吗?在Android中显示任何文件类型的任何通用方法? (因为我想支持许多文件类型)
选择了Uri:content://com.android.providers.media.documents/document/image:80
更新 根据@ CommonsWare的评论,我编辑了预览功能,如下所示:
fun showAttachmentPreviewer(uri: Uri, mimeType: String?) {
Log.d("TEST", "Preview " + uri.toString())
val intent = Intent(Intent.ACTION_VIEW, uri)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
val chooser = Intent.createChooser(intent, "Open with")
if (intent.resolveActivity(mContext.packageManager) != null)
mContext.startActivity(chooser)
else
mContext.showSnackBar("No suitable application to open file")
}
现在应用程序总是崩溃,崩溃日志如下:
java.lang.SecurityException:Uid 10202没有uri的权限 0 @ 内容://com.android.providers.media.documents/document/audio:17915
更新2:
我的应用在mContext.startActivity(chooser)
行崩溃了。这是完整的崩溃日志:
致命的例外:主要 处理:com.makeit.lite,PID:12851 java.lang.SecurityException:Uid 10477没有uri的权限 0 @ 内容://com.android.providers.media.documents/document/image:24776 在android.os.Parcel.readException(Parcel.java:1540) 在android.os.Parcel.readException(Parcel.java:1493) 在 android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:2514) 在 android.app.Instrumentation.execStartActivity(Instrumentation.java:1494) 在android.app.Activity.startActivityForResult(Activity.java:3913) 在 android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:50) 在 android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:79) 在android.app.Activity.startActivityForResult(Activity.java:3860) 在 android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:859) 在android.app.Activity.startActivity(Activity.java:4184) 在android.app.Activity.startActivity(Activity.java:4152) 在 com.makeit.lite.attachment.AttachmentNavigator.showAttachmentPreviewer(AttachmentNavigator.kt:92) 在 com.makeit.lite.attachment.list.AttachmentListPresenter.onAttachmentClicked(AttachmentListPresenter.kt:37) 在 com.makeit.lite.attachment.list.AttachmentListFragment $ onViewCreated $ 1.onItemClick(AttachmentListFragment.kt:39) 在 eu.davidea.viewholders.FlexibleViewHolder.onClick(FlexibleViewHolder.java:121) 在android.view.View.performClick(View.java:5156) 在android.view.View $ PerformClick.run(View.java:20755) 在android.os.Handler.handleCallback(Handler.java:739) 在android.os.Handler.dispatchMessage(Handler.java:95) 在android.os.Looper.loop(Looper.java:145) 在android.app.ActivityThread.main(ActivityThread.java:5835) at java.lang.reflect.Method.invoke(Native Method) 在java.lang.reflect.Method.invoke(Method.java:372) 在 com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:1399) 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
更新3:
如果我将mimeType设置为intent:intent.type = mimeType
并且应用程序不再崩溃。 mimeType
是我从选择器意图获得的字符串(在content:
uri旁边)。 mimeType值可以image/jpeg
或基于所选文件类型的任何内容。虽然它不会崩溃,但是给定uri的文件也不会显示。如果我从Intent-Chooser中选择Gallery
,则会打开并显示所有图像。我想第3个应用程序不知道如何在给定的uri确定文件。
以下是我的功能的最新来源:
fun showAttachmentPreviewer(uri: Uri, mimeType: String?) {
Log.d("TEST", "Preview " + uri.toString() + " For type" + mimeType)
val intent = Intent(Intent.ACTION_VIEW, uri)
intent.type = mimeType //Can be "image/jpeg" or sth corresponding to the filetype.
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
val chooser = Intent.createChooser(intent, "Open with")
if (intent.resolveActivity(mContext.packageManager) != null)
mContext.startActivity(chooser)
else
mContext.showSnackBar("No suitable application to open file")
}
答案 0 :(得分:3)
我是否使用错误的方法在Android中打开文件?
首先,可能没有能够查看文件类型的应用程序。
其次,您尚未授予该应用查看内容的权限。在 - (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"PPUSFAModel" withExtension:@"momd"];
//I earlier was PPUSFAModel 16, i added new model version PPUSFAModel 17.
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:SQLITENAME];
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
//Error
}
return _persistentStoreCoordinator;
}
- (void)saveContext
{
__block NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
[managedObjectContext performBlockAndWait:^{
if (managedObjectContext != nil && _persistentStoreCoordinator != nil) {
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
// DLog(@"Unresolved error %@, %@", error, [error userInfo]);
//abort();
}
} }];
}
上使用addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
。
答案 1 :(得分:0)
如果要对文件执行完美功能,则应使用任何第三方库来实现此功能。
您应该查看以下链接,了解文件选择器的最常见库: -
答案 2 :(得分:0)
val intent = Intent(Intent.ACTION_VIEW, uri)
intent.type = mimeType
更改为
val intent = Intent(Intent.ACTION_VIEW);
intent.setDataAndType (uri, mimeType );
您应该使用一个语句设置uri和mime类型。否则接收应用将为uri收到null。大多数应用程序不会告诉您他们没有收到uri。例如,Gallery应用程序没有。
我不知道Kotlin的确切功能名称。
答案 3 :(得分:0)
首先,我想对@GreenApps,@ Ankit和@CommonsWare表示感谢。谁花时间调查我的问题。
我在将源提取到分离的简单项目时终于找到了根本原因。这是因为我用这种方式将uri-string解析成uri-instance(根本原因的代码没有包含在我的问题中。我的道歉):
val uri = Uri.parse(URLDecoder.decode(uriString, "UTF-8")) as Uri
当我改为val uri = Uri.parse(uriString)
时,问题就解决了。
顺便说一下,我想在我的Github上分享选择器和预览器的示例代码,以便有人可能需要看看。 java源位于master
分支上,Kotlin源位于kotlin-version
分支上。使用这个简单的代码,现在我可以选择任何文件类型(图像,音频,视频,pdf,xlsx,...),然后通过Intent.ACTION_VIEW打开它。
这是: