我看了很多很多SO帖子来找到答案,但没有运气......
如何将公共存储中的文件作为电子邮件附件发送?
大多数帖子都在询问内部存储文件。因此,他们使用FileProvider
(或类似的东西)。在FileProvider
的文档中,我读到了:
FileProvider ...有助于安全共享与应用程序关联的文件...
但我要发送的文件与我的应用无关。它是Documents文件夹中公共存储中的.csv文件。所以我的应用程序设置一个具有公共文件访问权限的FileProvider似乎很奇怪。将我的包名称用作"权限"。
更奇怪我尝试了以下代码,我根据1或2个其他帖子中的答案将其放在一起:
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
File f = new File(path, _sFileName);
_sFileDir = f.getCanonicalPath();
我用另一种方法:
Intent i = new Intent(android.content.Intent.ACTION_SEND);
String Email[] = { "my.name@gmail.com" };
i.putExtra(android.content.Intent.EXTRA_EMAIL, Email);
i.putExtra(android.content.Intent.EXTRA_SUBJECT, "My Report");
i.setType("plain/text");
String sURI = "file:/" + _sFileDir;
i.putExtra(Intent.EXTRA_STREAM, Uri.parse(sURI));
startActivity(i);
这会导致应用程序崩溃并显示以下消息:" MyApp已停止"
当我改变"文件:/"到"内容:/"该应用程序不再崩溃,并且已发送电子邮件,但未附加任何文件。
我的AndroidManifest.xml包含以下权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
以下是我使用&#34;内容时的LogCat:/&#34;:
07-28 17:19:22.528 27809-27809/? I/art: Late-enabling -Xcheck:jni
07-28 17:19:22.569 27809-27816/? E/art: Failed sending reply to debugger: Broken pipe
07-28 17:19:22.569 27809-27816/? I/art: Debugger is no longer active
07-28 17:19:22.569 27809-27816/? I/art: Starting a blocking GC Instrumentation
07-28 17:19:22.582 27809-27809/? W/ActivityThread: Application com.myorg.myapp is waiting for the debugger on port 8100...
07-28 17:19:22.583 27809-27809/? I/System.out: Sending WAIT chunk
07-28 17:19:24.636 27809-27816/com.myorg.myapp I/art: Debugger is active
07-28 17:19:24.785 27809-27809/com.myorg.myapp I/System.out: Debugger has connected
07-28 17:19:24.785 27809-27809/com.myorg.myapp I/System.out: waiting for debugger to settle...
07-28 17:19:24.985 27809-27809/com.myorg.myapp I/System.out: waiting for debugger to settle...
07-28 17:19:25.186 27809-27809/com.myorg.myapp I/System.out: waiting for debugger to settle...
07-28 17:19:25.386 27809-27809/com.myorg.myapp I/System.out: waiting for debugger to settle...
07-28 17:19:25.588 27809-27809/com.myorg.myapp I/System.out: waiting for debugger to settle...
07-28 17:19:25.788 27809-27809/com.myorg.myapp I/System.out: waiting for debugger to settle...
07-28 17:19:25.989 27809-27809/com.myorg.myapp I/System.out: waiting for debugger to settle...
07-28 17:19:26.189 27809-27809/com.myorg.myapp I/System.out: debugger has settled (1454)
07-28 17:19:26.408 27809-27809/com.myorg.myapp W/System: ClassLoader referenced unknown path: /data/app/com.myorg.myapp-1/lib/arm
07-28 17:19:26.444 27809-27809/com.myorg.myapp I/InstantRun: starting instant run server: is main process
07-28 17:19:26.508 27809-27816/com.myorg.myapp I/art: Starting a blocking GC Instrumentation
07-28 17:19:26.801 27809-27809/com.myorg.myapp W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
07-28 17:19:28.471 27809-27814/com.myorg.myapp I/art: Do partial code cache collection, code=14KB, data=23KB
07-28 17:19:28.471 27809-27814/com.myorg.myapp I/art: After code cache collection, code=14KB, data=23KB
07-28 17:19:28.471 27809-27814/com.myorg.myapp I/art: Increasing code cache capacity to 128KB
07-28 17:19:28.475 27809-27814/com.myorg.myapp I/art: Do partial code cache collection, code=14KB, data=42KB
07-28 17:19:28.476 27809-27814/com.myorg.myapp I/art: After code cache collection, code=14KB, data=42KB
07-28 17:19:28.476 27809-27814/com.myorg.myapp I/art: Increasing code cache capacity to 256KB
07-28 17:19:29.036 27809-27814/com.myorg.myapp I/art: Do full code cache collection, code=119KB, data=108KB
07-28 17:19:29.037 27809-27814/com.myorg.myapp I/art: After code cache collection, code=113KB, data=86KB
07-28 17:19:29.216 27809-27895/com.myorg.myapp I/Adreno: QUALCOMM build : 7d18700, I8ee426a9a2
Build Date : 10/07/16
OpenGL ES Shader Compiler Version: XE031.09.00.03
Local Branch : mybranch22308589
Remote Branch : quic/LA.BR.1.3.6_rb1.6
Remote Branch : NONE
Reconstruct Branch : NOTHING
07-28 17:19:29.229 27809-27895/com.myorg.myapp I/OpenGLRenderer: Initialized EGL, version 1.4
07-28 17:19:29.229 27809-27895/com.myorg.myapp D/OpenGLRenderer: Swap behavior 1
07-28 17:19:29.388 27809-27814/com.myorg.myapp I/art: Do partial code cache collection, code=125KB, data=105KB
07-28 17:19:29.388 27809-27814/com.myorg.myapp I/art: After code cache collection, code=125KB, data=105KB
07-28 17:19:29.388 27809-27814/com.myorg.myapp I/art: Increasing code cache capacity to 512KB
07-28 17:19:29.691 27809-27809/com.myorg.myapp W/art: Before Android 4.1, method int android.support.v7.widget.ListViewCompat.lookForSelectablePosition(int, boolean) would have incorrectly overridden the package-private method in android.widget.ListView
07-28 17:19:29.701 27809-27809/com.myorg.myapp I/Choreographer: Skipped 97 frames! The application may be doing too much work on its main thread.
07-28 17:19:34.479 27809-27809/com.myorg.myapp I/Choreographer: Skipped 124 frames! The application may be doing too much work on its main thread.
07-28 17:19:37.417 27809-27809/com.myorg.myapp W/IInputConnectionWrapper: reportFullscreenMode on inexistent InputConnection
07-28 17:19:37.417 27809-27809/com.myorg.myapp W/IInputConnectionWrapper: finishComposingText on inactive InputConnection
07-28 17:19:41.841 27809-27814/com.myorg.myapp I/art: Do full code cache collection, code=252KB, data=246KB
07-28 17:19:41.844 27809-27814/com.myorg.myapp I/art: After code cache collection, code=248KB, data=216KB
07-28 17:19:45.257 27809-27809/com.myorg.myapp I/Choreographer: Skipped 204 frames! The application may be doing too much work on its main thread.
07-28 17:19:49.125 27809-27809/com.myorg.myapp W/IInputConnectionWrapper: reportFullscreenMode on inexistent InputConnection
07-28 17:19:49.126 27809-27809/com.myorg.myapp W/IInputConnectionWrapper: finishComposingText on inactive InputConnection
07-28 17:19:57.498 27809-27814/com.myorg.myapp I/art: Do partial code cache collection, code=250KB, data=227KB
07-28 17:19:57.499 27809-27814/com.myorg.myapp I/art: After code cache collection, code=250KB, data=227KB
07-28 17:19:57.499 27809-27814/com.myorg.myapp I/art: Increasing code cache capacity to 1024KB
07-28 17:20:12.117 27809-27809/com.myorg.myapp W/IInputConnectionWrapper: reportFullscreenMode on inexistent InputConnection
07-28 17:20:12.117 27809-27809/com.myorg.myapp W/IInputConnectionWrapper: finishComposingText on inactive InputConnection
这是&#34;文件中的另一个LogCat:/&#34;使用&amp;应用程序崩溃:
07-28 17:43:57.190 30651-30651/com.myorg.myapp D/AndroidRuntime: Shutting down VM
07-28 17:43:57.232 30651-30651/com.myorg.myapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.myorg.myapp, PID: 30651
java.lang.IllegalStateException: Could not execute method for android:onClick
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:293)
at android.view.View.performClick(View.java:5612)
at android.view.View$PerformClick.run(View.java:22285)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6123)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
at android.view.View.performClick(View.java:5612)
at android.view.View$PerformClick.run(View.java:22285)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6123)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
Caused by: android.os.FileUriExposedException: file://storage/emulated/0/Documents/Tasks.csv exposed beyond app through ClipData.Item.getUri()
at android.os.StrictMode.onFileUriExposed(StrictMode.java:1813)
at android.net.Uri.checkFileUriExposed(Uri.java:2360)
at android.content.ClipData.prepareToLeaveProcess(ClipData.java:832)
at android.content.Intent.prepareToLeaveProcess(Intent.java:8957)
at android.content.Intent.prepareToLeaveProcess(Intent.java:8942)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1583)
at android.app.Activity.startActivityForResult(Activity.java:4228)
at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:50)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:79)
at android.app.Activity.startActivityForResult(Activity.java:4187)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:859)
at android.app.Activity.startActivity(Activity.java:4515)
at android.app.Activity.startActivity(Activity.java:4483)
at com.myorg.myapp.MainActivity.onClickSend(ProgSummary.java:209)
at java.lang.reflect.Method.invoke(Native Method)
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
at android.view.View.performClick(View.java:5612)
at android.view.View$PerformClick.run(View.java:22285)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6123)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
这样做的正确方法是什么?
新信息:
当我使用&#34;内容:/&#34;时,我这次在Gmail应用上看到一条消息(Toast?)短暂闪烁,说&#34;无法附加空文件&#34; ;。但它不是空的!!!
更多新信息:
我尝试使用FileProvider来执行此操作。这是代码......
的AndroidManifest.xml:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.myorg.myapp.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
filepaths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="publicdocuments/" path="documents/" />
</paths>
MainActivity.java:
public void onClickSend(View v) {
Intent i = new Intent(android.content.Intent.ACTION_SEND);
String Email[] = { "my.address@gmail.com" };
i.putExtra(android.content.Intent.EXTRA_EMAIL, Email);
i.putExtra(android.content.Intent.EXTRA_SUBJECT, "Report");
i.setType("text/plain");
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
File f = new File(path, "file.csv");
Uri sUri = FileProvider.getUriForFile(MainActivity.this, "com.myorg.myapp.fileprovider", f);
i.setData(sUri);
i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(i);
}
现在的问题是它无法正常工作 - 我的应用程序在调用FileProvider.getUriForFile()
时再次崩溃。
这是新的LogCat:
--------- beginning of crash
07-29 13:45:27.116 10397-10397/com.myorg.myapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.myorg.myapp, PID: 10397
java.lang.IllegalStateException: Could not execute method for android:onClick
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:293)
at android.view.View.performClick(View.java:5612)
at android.view.View$PerformClick.run(View.java:22285)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6123)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
at android.view.View.performClick(View.java:5612)
at android.view.View$PerformClick.run(View.java:22285)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6123)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
Caused by: java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Documents/Tasks.csv
at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:711)
at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:400)
at com.myorg.myapp.MainActivity.onClickSend(MainActivity.java:214)
at java.lang.reflect.Method.invoke(Native Method)
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
at android.view.View.performClick(View.java:5612)
at android.view.View$PerformClick.run(View.java:22285)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6123)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
如你所见,有一个InvocationTargetException,但我不知道为什么......
其他信息:在FileProvider.getUriForFile()中使用v.getContext()替换MainActivity.this会产生相同的结果。
答案 0 :(得分:0)
所以我的应用程序设置一个具有公共文件访问权限的FileProvider似乎很奇怪
您尝试发送的应用可能没有外部存储访问权限。因此,FileProvider
仍然是推荐的模式。
这导致应用程序崩溃并显示消息:“MyApp已停止”
Use LogCat to examine the Java stack trace与任何应用程序“MyApp”中的崩溃相关联。
另请注意,plain/text
不是有效的MIME类型。大概你的意思是text/plain
。
并且,在File
的情况下,使用Uri.fromFile()
为其生成Uri
。请注意,使用file
方案时,您的应用可能会因Android 7.0+而崩溃,这是使用FileProvider
的另一个原因。
这样做的正确方法是什么?
使用FileProvider
。