当我尝试打开文件时,应用程序崩溃了.它可以在Android Nougat下运行,但在Android Nougat上它会崩溃.当我尝试从SD卡打开文件而不是从系统分区打开文件时,它只会崩溃.一些许可问题?
示例代码:
File file = new File("/storage/emulated/0/test.txt");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "text/*");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent); // Crashes on this line
Run Code Online (Sandbox Code Playgroud)
日志:
android.os.FileUriExposedException:file:///storage/emulated/0/test.txt通过Intent.getData()暴露在app之外
编辑:
在定位Android Nougat时,file://
不再允许使用URI.我们应该使用content://
URI代替.但是,我的应用程序需要打开根目录中的文件.有任何想法吗?
我有两个应用程序:app1和app2.
App2有:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.android.provider.ImageSharing"
android:exported="false"
android:grantUriPermissions="true" >
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/paths" />
</provider>
Run Code Online (Sandbox Code Playgroud)
paths.xml:
<paths>
<files-path name="my_images" path="images/"/>
</paths>
Run Code Online (Sandbox Code Playgroud)
App2从App1的Activity中接收请求以获取图像的URI.确定URI后,App2活动执行以下操作:
Intent intent = new Intent();
intent.setDataAndType(contentUri, getContentResolver().getType(contentUri));
int uid = Binder.getCallingUid();
String callingPackage = getPackageManager().getNameForUid(uid);
getApplicationContext().grantUriPermission(callingPackage, contentUri,
Intent.FLAG_GRANT_READ_URI_PERMISSION);
setResult(Activity.RESULT_OK, intent);
finish();
Run Code Online (Sandbox Code Playgroud)
从App2收到结果后,App1执行以下操作:
Uri imageUri = data.getData();
if(imageUri != null) {
ImageView iv = (ImageView) layoutView.findViewById(R.id.imageReceived);
iv.setImageURI(imageUri);
}
Run Code Online (Sandbox Code Playgroud)
在App1中,从App2返回时,我得到以下异常:
java.lang.SecurityException:Permission Denial:从ProcessRecord {52a99eb0 3493:com.android.App1.app/u0a57}(pid = 3493,uid = 10057)打开提供者android.support.v4.content.FileProvider uid 10058
我究竟做错了什么 ?
我正在尝试将Camera App存储到我的内部存储器中.我也理解第三方应用程序无法访问我的应用程序的内部存储,但我们可以通过公开内部目录来实现FileProvider
.我在这里遵循了指南:
我AndroidManifest.xml
用以下方式指定我:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.stackoverflow.test.camerawithfileprovider" >
<application>
<activity
...
</activity>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.stackoverflow.test.camerawithfileprovider.fileprovider"
android:exported="false"
android:grantUriPermissions="true" >
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider_path" />
</provider>
</application>
</manifest>
Run Code Online (Sandbox Code Playgroud)
我创建了一个名为xml文件file_provider_path.xml
中/res/xml/
:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="image_capture" path="public/" />
</paths>
Run Code Online (Sandbox Code Playgroud)
这就是我创建和调用Camera Intent的方法:
private static final int CAMERA_REQUEST_CODE = 5000;
private static final String CAMERA_FP_AUTHORITY = "com.stackoverflow.test.camerawithfileprovider.fileprovider";
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
Context context = MainActivity.this;
File imagePath = new File(context.getFilesDir(), …
Run Code Online (Sandbox Code Playgroud) 我在FileProviders上的android开发人员参考上遵循了示例代码,但它不起作用.
我files/exports/
在我的Manifest中的文件提供程序定义中设置了路径,并且引用的文件确实存在于该路径中.
在我的清单中:
<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.company.app.fileprovider" android:exported="false" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" />
</provider>
Run Code Online (Sandbox Code Playgroud)
并在 xml/file_paths.xml
<?xml version="1.0" encoding="UTF-8" ?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="exports" path="exports/"/>
</paths>
Run Code Online (Sandbox Code Playgroud)
然后我尝试使用以下代码获取content-uri:
Java.IO.File exportFile =
new Java.IO.File ("/data/data/com.company.app/files/exports/file.pdf");
Android.Net.Uri exportUri =
Android.Support.V4.Content.FileProvider.GetUriForFile (this, "com.company.app.fileprovider", exportFile);
Run Code Online (Sandbox Code Playgroud)
但是我收到此错误:
Exception of type 'Java.Lang.NullPointerException' was thrown.
at Android.Runtime.JNIEnv.CallStaticObjectMethod (IntPtr jclass, IntPtr jmethod, Android.Runtime.JValue[] parms) [0x00064] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.10.2-branch/4b53fbd0/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:1160
at Android.Support.V4.Content.FileProvider.GetUriForFile (Android.Content.Context context, System.String authority, Java.IO.File file) [0x00000] in <filename unknown>:0
at com.company.App.ImageAndSubtitle.cloudStorageDidDownloadFile (System.Object sender, com.company.App.CloudStorageEventArgs …
Run Code Online (Sandbox Code Playgroud) 我有一个问题,我正在尝试将多个文件从我的内部存储附加到电子邮件意图,方法是使用我的清单中声明的FileProvider并授予读取uri权限.这是我的代码.
表现
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.company.example.logprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
Run Code Online (Sandbox Code Playgroud)
意图创造
emailIntent = new Intent(android.content.Intent.ACTION_SEND_MULTIPLE);
emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,new String[] {"randomemailaddress"});
ArrayList<Uri> uris = new ArrayList<Uri>();
File directory = getFilesDir();
File[] list = directory.listFiles();
for (File f : list) {
if (f.getName().contains("log") && f.getName().contains(".txt"))
uris.add(FileProvider.getUriForFile(this, "com.company.example.logprovider",f));
}
emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
Run Code Online (Sandbox Code Playgroud)
问题
这适用于运行Jelly Bean的两台设备,但它不适用于运行姜饼的两台设备.
我得到的例外情况如下.
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.google.android.gm/com.google.android.gm.ComposeActivity}: java.lang.SecurityException: Permission Denial: opening provider android.support.v4.content.FileProvider from ProcessRecord{40b2db08 3885:com.google.android.gm/10110} (pid=3885, uid=10110) requires null or null
E/AndroidRuntime( 3885): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1659)
E/AndroidRuntime( 3885): at …
Run Code Online (Sandbox Code Playgroud) 我们正在关注从应用程序到 Instagram 分享故事的官方文档
https://developers.facebook.com/docs/instagram/sharing-to-stories/
预期的行为是,当我尝试分享故事时,Instagram 应用程序的故事屏幕应该打开,并在意图中发送图像。实际行为是 instagram 应用程序未打开且用户停留在同一屏幕上。
// Define image asset URI and attribution link URL
Uri backgroundAssetUri = "your-image-asset-uri-goes-here;"
String attributionLinkUrl = "https://www.my-aweseome-app.com/p/BhzbIOUBval/";
// Instantiate implicit intent with ADD_TO_STORY action,
// background asset, and attribution link
Intent intent = new Intent("com.instagram.share.ADD_TO_STORY");
intent.setDataAndType(backgroundAssetUri, MEDIA_TYPE_JPEG);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra("content_url", attributionLinkUrl);
// Instantiate activity and verify it will resolve implicit intent
Activity activity = getActivity();
if (activity.getPackageManager().resolveActivity(intent, 0) != null) {
activity.startActivityForResult(intent, 0);
}
Run Code Online (Sandbox Code Playgroud) 我按照android docs的建议在内部存储上创建文件.准确地说,文件是在内部存储中的特定目录下创建的.我使用模式world_readable模式执行此操作.然后我尝试使用电子邮件程序附加文件.我能够连接文件,但发送电子邮件失败(似乎不是加载文件)我相信它是内部存储/许可的东西.
任何人都知道如何解决它或一个工作的例子?将外部存储上的所有东西都转换成是很糟糕的.
谢谢
Ps:我检查了其他线程,他们似乎没有解决方案(旧线程)
从Android N及以上我面临这个问题.当我从左侧文件选择器抽屉上的任何应用程序中选择一个文件(例如图库和文件管理器)时,会收到URI,我可以使用文件执行我需要的操作.
此外,如果我在文件选择器的抽屉中突出显示图像/视频/音频选项卡时选择了一个文件,我选择的任何文件都会成功返回它的URI.
在我的onActivity Result中,
Log.i("File URI to String", data.getDataString());
输出
I/File URI to String: content://com.android.providers.media.documents/document/image%3A20399
我可以使用下面的GetPath方法获取文件路径.
但是,当我只选择内部或外部存储突出显示的选择器,注意发生,Log.i("File URI to String", data.getDataString());
输出
I/File URI to String: content://com.android.externalstorage.documents/document/CA8B-8BD2%3ADCIM%2F100ANDRO%2FDSC_0001.JPG
我的getPath方法无法获得路径,我认为它可能与提供商有关,看看uris之间的差异以字符串形式.
我如何获得这些选择的文件路径似乎不受任何提供商的支持.任何帮助表示赞赏.
我的代码启动文件选择器:
Intent intent = new Intent();
intent.setType("*/*");
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intent, DEFAULT_IMAGE_PICK);
Run Code Online (Sandbox Code Playgroud)
当我启动文件选择器意图时
2018-10-23 21:51:26.345 1572-10747/? I/ActivityManager: START u0 {act=android.intent.action.OPEN_DOCUMENT cat=[android.intent.category.OPENABLE] typ=*/* cmp=com.android.documentsui/.picker.PickActivity (has extras)} from uid 10298
2018-10-23 21:51:26.352 1572-10747/? D/ActivityTrigger: activityStartTrigger: Activity is Triggerred in full screen ApplicationInfo{e1aa80b com.android.documentsui}
2018-10-23 21:51:26.352 1572-10747/? E/ActivityTrigger: activityStartTrigger: not whiteListedcom.android.documentsui/com.android.documentsui.picker.PickActivity/26
2018-10-23 …
Run Code Online (Sandbox Code Playgroud) 我有一个Android应用程序,基本上存储了保存在用户手机上的gpx文件列表.当用户点击应用程序中的文件名时,它应该提示用户打开gpx文件,其中包含手机上可用的任何路由应用程序.现在我正在测试在奥斯曼打开文件.问题是,奥斯曼德正在开放,但随后立即崩溃.
尝试打开文件的代码是这样的:
File gpxFile = new File(Path);
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
Uri gpxUri = FileProvider.getUriForFile(view.getContext(), AUTHORITY, gpxFile);
intent.setDataAndType(gpxUri, "application/gpx+xml");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Run Code Online (Sandbox Code Playgroud)
gpx文件看起来像这样:
<?xml version="1.0"?>
<gpx creator="{CREATOR}" version="1.1" xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
<wpt lat="{LAT_1}" lon="{LON_1}">
<name>{WPT_NAME_1}</name>
</wpt>
...
<wpt lat="{LAT_N}" lon="{LON_N}">
<name>{WPT_NAME_N}</name>
</wpt>
<trk>
<name>{TRACK_NAME}</name>
<trkseg>
<trkpt lat="{LAT_1}" lon="{LON_1}"></trkpt>
...
<trkpt lat="{LAT_N}" lon="{LON_N}"></trkpt>
</trkseg>
</trk>
</gpx>
Run Code Online (Sandbox Code Playgroud)
起初我认为gpx文件的格式有问题,但如果我手动打开Osmand并尝试使用"配置地图" - >"Gpx轨道"导入文件,则轨迹在地图上显示正常,包括航点.
LE:这是我在奥斯曼试图开始时得到的错误:
08-16 17:28:00.524 5681-5762/? E/net.osmand: RenderingRuleProperty Rendering parse in strokeWidth_2
08-16 17:28:00.524 5681-5762/? E/net.osmand: RenderingRuleProperty Rendering parse in strokeWidth_2
08-16 …
Run Code Online (Sandbox Code Playgroud) 我尝试通过手动启动Google驱动器(安装在设备上)从我的Android应用程序上传文件.我尝试使用Intent.createChooser
它来发送文件附件,并且工作正常.但我需要上传特定意图的文件(例如Dropbox,仅限Google云端硬盘).所以我更改了代码并尝试按以下方式将文件上传到Google云端硬盘,但没有成功,只有Google云端硬盘应用在设备上打开,没有上传文件:
PackageManager pm = this.getPackageManager();
Intent intent = pm.getLaunchIntentForPackage("com.google.android.apps.docs");
intent.setType("application/pdf");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://sdcard/sdcard0/test.pdf"));
intent.putExtra(Intent.EXTRA_SUBJECT, "attach a file test");
intent.addCategory(Intent.ACTION_ATTACH_DATA);
startActivity(intent);
Run Code Online (Sandbox Code Playgroud)
我们可以通过手动打开意图上传PDF文件吗?
这个问题包含几个子问题.从这个问题开始,我正在分叉这些.我最终会通过删除这个问题进行清理.
理论上,以下程序将共享一个hello-world文本文件.代码运行,但共享到Dropbox或Gmail(仅通过两个具体示例)失败.
public class MainActivity extends Activity {
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String filename = "hellow.txt";
String fileContents = "Hello, World!\n";
byte[] bytes = fileContents.getBytes();
FileOutputStream fos = null;
try {
fos = this.openFileOutput(filename, MODE_PRIVATE);
fos.write(bytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
File file = new File(filename);
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
shareIntent.setType("application/txt");
startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.send_to)));
file.delete();
} …
Run Code Online (Sandbox Code Playgroud) 我正在开发一个通过电子邮件发送处理报告的应用程序。当在应用程序中完成处理数据时,用户会发送一封包含处理数据的电子邮件。但是,我在 Android 11 上遇到了问题。将报告附加到电子邮件时,无论电子邮件应用程序如何,都会出现一条消息:无法附加文件。我一直在研究,发现这可能与在 android 11 版本的设备上访问设备内部存储的权限有关。我希望我能帮助您发送带有 android 11 附加文件的电子邮件。
我的代码:清单
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:requestLegacyExternalStorage="true"
tools:ignore="AllowBackup"
tools:targetApi="n">
<activity.....
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
Run Code Online (Sandbox Code Playgroud)
我的xml:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="."/>
</paths>
Run Code Online (Sandbox Code Playgroud)
保存文件 .pdf
val mDocProc = Document()
val file =
File(
Environment.getExternalStorageDirectory()
.toString() + "/" + "Relatório diário" + date + ".pdf"
)
if (file.exists()) { …
Run Code Online (Sandbox Code Playgroud) 我正在尝试整合在Android中拍照.在运行我正在运行的应用程序并且错误" 不幸的是,相机已停止 ",但我的应用程序没有崩溃.我在Android"KITKAT"中发现了这个问题.这是我用来拍照的示例代码,
使用这个功能我正在拍照,
private void take_picture_intent() {
Intent takePictureIntent = (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT)
? new Intent(MediaStore.ACTION_IMAGE_CAPTURE_SECURE)
: new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(this.getActivity().getPackageManager()) != null) {
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException e) {
e.printStackTrace();
}
if (photoFile != null) {
photoURI = FileProvider.getUriForFile(this.getActivity(), "com.android.myapplication.fileprovider", photoFile);
Log.e(TAG, "photoFile: "+photoFile+" ,URI : "+photoURI.getPath());
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
getActivity().startActivityForResult(takePictureIntent, SelectMedia.IMAGE_CAPTURE_AT_THE_DOOR);
}
}
}
Run Code Online (Sandbox Code Playgroud)
此函数用于生成图像路径,
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = …
Run Code Online (Sandbox Code Playgroud)