Damon Getsman
Newbie
Hi everybody. I'm having a problem that I can't get to the bottom of, while trying to share a file by becoming a FileProvider in my app. I think that my issue is coming from an incorrect provider authority, but I'm not sure. This is definitely my first time with working with these authorities, or any sort of Intents other than opening a new activity, so I'm in virgin territory here. Googling isn't turning up much for me, and the error message that I'm receiving isn't giving me much to go on here. I'll just go ahead and paste the stack trace first, as I'm not even sure at this point what parts of it are relevant and not...
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.sprite.half_lifetimer, PID: 18548
java.lang.IllegalStateException: Could not execute method for androidnClick
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:390)
at android.view.View.performClick(View.java:6274)
at android.view.View$PerformClick.run(View.java:24859)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6710)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:770)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
at android.view.View.performClick(View.java:6274)
at android.view.View$PerformClick.run(View.java:24859)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6710)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:770)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference
at android.support.v4.content.FileProvider.parsePathStrategy(FileProvider.java:605)
at android.support.v4.content.FileProvider.getPathStrategy(FileProvider.java:579)
at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:417)
at com.example.sprite.half_lifetimer.ExportDatabase.shareJSON(ExportDatabase.java:109)
at java.lang.reflect.Method.invoke(Native Method)
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
at android.view.View.performClick(View.java:6274)
at android.view.View$PerformClick.run(View.java:24859)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6710)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:770)
Code for the activity, which I am attempting to share from (ExportDatabase.java), with this error, follows:
AndroidManifest.xml follows:
And finally, file_paths.xml follows:
I've looked through multiple tutorials on sharing a file via Intent, and haven't been able to get any of them to work properly in my case. I'm sure that what I'm missing is something fairly trivial, as the basics seem, well, basic enough; I think I just haven't hodgepodged the pieces together correctly.
Oh, for what it's worth, I also know that the file that I'm trying to share should be "text/json", not "text/plain". I'm currently testing it as "text/plain" just to make sure that there are other apps set up that will be able to receive it when I'm debugging. After that bit, I intend to either relabel it as "text/json", or perhaps compress it for transmission to ES File Explorer or something that will allow me to sftp or otherwise send it to a desktop easily. Also, my apologies for the large amounts of commented out code inline; as you can see, I've made several attempts along different routes from the different examples I've been examining.
I really appreciate whatever kinds of issues you may be able to help me locate in this, as well as any time spent assisting on this matter. Thanks in advance!
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.sprite.half_lifetimer, PID: 18548
java.lang.IllegalStateException: Could not execute method for androidnClick
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:390)
at android.view.View.performClick(View.java:6274)
at android.view.View$PerformClick.run(View.java:24859)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6710)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:770)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
at android.view.View.performClick(View.java:6274)
at android.view.View$PerformClick.run(View.java:24859)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6710)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:770)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference
at android.support.v4.content.FileProvider.parsePathStrategy(FileProvider.java:605)
at android.support.v4.content.FileProvider.getPathStrategy(FileProvider.java:579)
at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:417)
at com.example.sprite.half_lifetimer.ExportDatabase.shareJSON(ExportDatabase.java:109)
at java.lang.reflect.Method.invoke(Native Method)
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
at android.view.View.performClick(View.java:6274)
at android.view.View$PerformClick.run(View.java:24859)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6710)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:770)
Code for the activity, which I am attempting to share from (ExportDatabase.java), with this error, follows:
Code:
package com.example.sprite.half_lifetimer;
import android.content.Intent;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.lang.reflect.Array;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import static android.support.v4.content.FileProvider.getUriForFile;
public class ExportDatabase extends AppCompatActivity {
boolean prettyPrinting = false;
String usagesFN = "usages.json";
String substancesFN = "substances.json";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_export_database);
updateDisplay();
}
private void updateDisplay() {
LinearLayout lloJSONtxt = findViewById(R.id.lloDBDump);
LinearLayout lloDumpStats = findViewById(R.id.lloDumpStats);
TextView tvwJSON = new TextView(this);
TextView tvwDumpStats = new TextView(this);
tvwJSON.setText(generateJSON());
lloJSONtxt.removeAllViewsInLayout();
lloJSONtxt.addView(tvwJSON);
tvwDumpStats.setText(
getResources().getString(R.string.json_resides_in, this.getFilesDir()));
lloDumpStats.removeAllViewsInLayout();
lloDumpStats.addView(tvwDumpStats);
}
private String generateJSON() {
Gson gson;
List<Usage> allUsages = Permanence.loadUsages();
List<Substance> allSubstances = Permanence.loadSubstances(this);
String substancesJSON;
String usagesJSON;
if (prettyPrinting) {
gson = new GsonBuilder().setPrettyPrinting().create();
} else {
gson = new Gson();
}
substancesJSON = gson.toJson(allSubstances);
usagesJSON = gson.toJson(allUsages);
try {
File usagesFile = new File(this.getFilesDir(), usagesFN);
File substancesFile = new File(this.getFilesDir(), substancesFN);
FileOutputStream usagesIS = new FileOutputStream(usagesFile);
FileOutputStream substancesIS = new FileOutputStream(substancesFile);
OutputStreamWriter usagesOSW = new OutputStreamWriter(usagesIS);
OutputStreamWriter substancesOSW = new OutputStreamWriter(substancesIS);
Writer usagesW = new BufferedWriter(usagesOSW);
Writer substancesW = new BufferedWriter(substancesOSW);
usagesW.write(usagesJSON);
substancesW.write(substancesJSON);
usagesW.close();
substancesW.close();
} catch (FileNotFoundException ex) {
GlobalMisc.showSimpleDialog(this, "Exception", "File not found " +
"exception!\n" + ex.toString());
} catch (IOException ex) {
GlobalMisc.showSimpleDialog(this, "Exception", "Input/Output " +
"exception!\n" + ex.toString());
}
return "Substances JSON\n\n" + substancesJSON + "\n\nUsages JSON\n\n" + usagesJSON;
}
public void togglePretty(View v) {
prettyPrinting = !prettyPrinting;
updateDisplay();
}
public void shareJSON(View v) {
File filesDirPath = new File(getFilesDir(), "files");
filesDirPath.mkdirs();
File usagesFile = new File(filesDirPath, usagesFN);
File substancesFile = new File(this.getFilesDir(), substancesFN);
Uri usagesUri = getUriForFile(this, "com.example.sprite.fileprovider", usagesFile);
/*Uri substancesUri = getUriForFile(this, "com.example.sprite.half_lifetimer.fileprovider",
substancesFile);*/
Intent intentShareJSON = new Intent(Intent.ACTION_SEND);
//intentShareJSON.setType(URLConnection.guessContentTypeFromName(usagesFN));
intentShareJSON.setType("text/plain");
/*intentShareJSON.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://" + this.getFilesDir() +
"/" + usagesFN));*/
//intentShareJSON.setData(usagesUri);
intentShareJSON.putExtra(Intent.EXTRA_STREAM, usagesUri);
startActivity(Intent.createChooser(intentShareJSON, "Share JSON"));
}
}
AndroidManifest.xml follows:
Code:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.sprite.half_lifetimer">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".ExportDatabase"></activity>
<activity android:name=".ConsolidateDatabase" />
<activity android:name=".DailyStats" />
<activity android:name=".DatabaseMaint" />
<activity android:name=".SubClassTabbedData" />
<activity
android:name=".SubClass"
android:label="@string/title_activity_sub_class"
android:theme="@style/AppTheme.NoActionBar" />
<activity android:name=".DosageGraphing" />
<activity android:name=".UsualSuspects" />
<activity android:name=".AddPastUsage" />
<activity android:name=".SubsRankedByLastUsage" />
<activity android:name=".FullAdminsDumpByID" />
<activity android:name=".FullAdminsDump" />
<activity android:name=".TabbedData" />
<activity android:name=".AdminData" />
<activity
android:name=".SubData"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths">
</meta-data>
</provider>
</application>
</manifest>
And finally, file_paths.xml follows:
Code:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="files" path="files/" />
</paths>
I've looked through multiple tutorials on sharing a file via Intent, and haven't been able to get any of them to work properly in my case. I'm sure that what I'm missing is something fairly trivial, as the basics seem, well, basic enough; I think I just haven't hodgepodged the pieces together correctly.
Oh, for what it's worth, I also know that the file that I'm trying to share should be "text/json", not "text/plain". I'm currently testing it as "text/plain" just to make sure that there are other apps set up that will be able to receive it when I'm debugging. After that bit, I intend to either relabel it as "text/json", or perhaps compress it for transmission to ES File Explorer or something that will allow me to sftp or otherwise send it to a desktop easily. Also, my apologies for the large amounts of commented out code inline; as you can see, I've made several attempts along different routes from the different examples I've been examining.
I really appreciate whatever kinds of issues you may be able to help me locate in this, as well as any time spent assisting on this matter. Thanks in advance!