1. Are you ready for the Galaxy S20? Here is everything we know so far!

Problem with sharing a file via Intent with another app as a FileProvider

Discussion in 'Android Development' started by Damon Getsman, Aug 8, 2019.

  1. Damon Getsman

    Damon Getsman Newbie
    Thread Starter

    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 android:eek:nClick
    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 (Text):
    1.  
    2. package com.example.sprite.half_lifetimer;
    3.  
    4. import android.content.Intent;
    5. import android.net.Uri;
    6. import android.support.v7.app.AppCompatActivity;
    7. import android.os.Bundle;
    8. import android.view.View;
    9. import android.widget.LinearLayout;
    10. import android.widget.TextView;
    11.  
    12. import com.google.gson.Gson;
    13. import com.google.gson.GsonBuilder;
    14.  
    15. import java.io.BufferedWriter;
    16. import java.io.File;
    17. import java.io.FileNotFoundException;
    18. import java.io.FileOutputStream;
    19. import java.io.IOException;
    20. import java.io.OutputStreamWriter;
    21. import java.io.Writer;
    22. import java.lang.reflect.Array;
    23. import java.net.URLConnection;
    24. import java.util.ArrayList;
    25. import java.util.List;
    26.  
    27. import static android.support.v4.content.FileProvider.getUriForFile;
    28.  
    29. public class ExportDatabase extends AppCompatActivity {
    30.  
    31.     boolean prettyPrinting = false;
    32.     String usagesFN = "usages.json";
    33.     String substancesFN = "substances.json";
    34.  
    35.     @Override
    36.     protected void onCreate(Bundle savedInstanceState) {
    37.         super.onCreate(savedInstanceState);
    38.         setContentView(R.layout.activity_export_database);
    39.  
    40.         updateDisplay();
    41.     }
    42.  
    43.     private void updateDisplay() {
    44.         LinearLayout lloJSONtxt = findViewById(R.id.lloDBDump);
    45.         LinearLayout lloDumpStats = findViewById(R.id.lloDumpStats);
    46.         TextView tvwJSON = new TextView(this);
    47.         TextView tvwDumpStats = new TextView(this);
    48.  
    49.         tvwJSON.setText(generateJSON());
    50.         lloJSONtxt.removeAllViewsInLayout();
    51.         lloJSONtxt.addView(tvwJSON);
    52.  
    53.         tvwDumpStats.setText(
    54.                 getResources().getString(R.string.json_resides_in, this.getFilesDir()));
    55.         lloDumpStats.removeAllViewsInLayout();
    56.         lloDumpStats.addView(tvwDumpStats);
    57.     }
    58.  
    59.     private String generateJSON() {
    60.         Gson gson;
    61.         List<Usage> allUsages = Permanence.loadUsages();
    62.         List<Substance> allSubstances = Permanence.loadSubstances(this);
    63.         String substancesJSON;
    64.         String usagesJSON;
    65.  
    66.         if (prettyPrinting) {
    67.             gson = new GsonBuilder().setPrettyPrinting().create();
    68.         } else {
    69.             gson = new Gson();
    70.         }
    71.         substancesJSON = gson.toJson(allSubstances);
    72.         usagesJSON = gson.toJson(allUsages);
    73.  
    74.         try {
    75.             File usagesFile = new File(this.getFilesDir(), usagesFN);
    76.             File substancesFile = new File(this.getFilesDir(), substancesFN);
    77.             FileOutputStream usagesIS = new FileOutputStream(usagesFile);
    78.             FileOutputStream substancesIS = new FileOutputStream(substancesFile);
    79.             OutputStreamWriter usagesOSW = new OutputStreamWriter(usagesIS);
    80.             OutputStreamWriter substancesOSW = new OutputStreamWriter(substancesIS);
    81.             Writer usagesW = new BufferedWriter(usagesOSW);
    82.             Writer substancesW = new BufferedWriter(substancesOSW);
    83.  
    84.             usagesW.write(usagesJSON);
    85.             substancesW.write(substancesJSON);
    86.             usagesW.close();
    87.             substancesW.close();
    88.         } catch (FileNotFoundException ex) {
    89.             GlobalMisc.showSimpleDialog(this, "Exception", "File not found " +
    90.                     "exception!\n" + ex.toString());
    91.         } catch (IOException ex) {
    92.             GlobalMisc.showSimpleDialog(this, "Exception", "Input/Output " +
    93.                     "exception!\n" + ex.toString());
    94.         }
    95.  
    96.         return "Substances JSON\n\n" + substancesJSON + "\n\nUsages JSON\n\n" + usagesJSON;
    97.     }
    98.  
    99.     public void togglePretty(View v) {
    100.         prettyPrinting = !prettyPrinting;
    101.  
    102.         updateDisplay();
    103.     }
    104.  
    105.     public void shareJSON(View v) {
    106.         File filesDirPath = new File(getFilesDir(), "files");
    107.         filesDirPath.mkdirs();
    108.         File usagesFile = new File(filesDirPath, usagesFN);
    109.         File substancesFile = new File(this.getFilesDir(), substancesFN);
    110.         Uri usagesUri = getUriForFile(this, "com.example.sprite.fileprovider", usagesFile);
    111.         /*Uri substancesUri = getUriForFile(this, "com.example.sprite.half_lifetimer.fileprovider",
    112.                 substancesFile);*/
    113.  
    114.         Intent intentShareJSON = new Intent(Intent.ACTION_SEND);
    115.  
    116.         //intentShareJSON.setType(URLConnection.guessContentTypeFromName(usagesFN));
    117.         intentShareJSON.setType("text/plain");
    118.         /*intentShareJSON.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://" + this.getFilesDir() +
    119.                 "/" + usagesFN));*/
    120.         //intentShareJSON.setData(usagesUri);
    121.         intentShareJSON.putExtra(Intent.EXTRA_STREAM, usagesUri);
    122.  
    123.         startActivity(Intent.createChooser(intentShareJSON, "Share JSON"));
    124.     }
    125. }
    126.  
    AndroidManifest.xml follows:
    Code (Text):
    1.  
    2. <?xml version="1.0" encoding="utf-8"?>
    3. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    4.     package="com.example.sprite.half_lifetimer">
    5.  
    6.     <application
    7.         android:allowBackup="true"
    8.         android:icon="@mipmap/ic_launcher"
    9.         android:label="@string/app_name"
    10.         android:roundIcon="@mipmap/ic_launcher_round"
    11.         android:supportsRtl="true"
    12.         android:theme="@style/AppTheme">
    13.         <activity android:name=".ExportDatabase"></activity>
    14.         <activity android:name=".ConsolidateDatabase" />
    15.         <activity android:name=".DailyStats" />
    16.         <activity android:name=".DatabaseMaint" />
    17.         <activity android:name=".SubClassTabbedData" />
    18.         <activity
    19.             android:name=".SubClass"
    20.             android:label="@string/title_activity_sub_class"
    21.             android:theme="@style/AppTheme.NoActionBar" />
    22.         <activity android:name=".DosageGraphing" />
    23.         <activity android:name=".UsualSuspects" />
    24.         <activity android:name=".AddPastUsage" />
    25.         <activity android:name=".SubsRankedByLastUsage" />
    26.         <activity android:name=".FullAdminsDumpByID" />
    27.         <activity android:name=".FullAdminsDump" />
    28.         <activity android:name=".TabbedData" />
    29.         <activity android:name=".AdminData" />
    30.         <activity
    31.             android:name=".SubData"
    32.             android:label="@string/app_name"
    33.             android:theme="@style/AppTheme.NoActionBar">
    34.             <intent-filter>
    35.                 <action android:name="android.intent.action.MAIN" />
    36.  
    37.                 <category android:name="android.intent.category.LAUNCHER" />
    38.             </intent-filter>
    39.         </activity>
    40.  
    41.         <provider
    42.             android:name="android.support.v4.content.FileProvider"
    43.             android:authorities="com.example.provider"
    44.             android:exported="false"
    45.             android:grantUriPermissions="true">
    46.             <meta-data
    47.                 android:name="android.support.FILE_PROVIDER_PATHS"
    48.                 android:resource="@xml/file_paths">
    49.             </meta-data>
    50.         </provider>
    51.  
    52.     </application>
    53.  
    54. </manifest>
    55.  
    And finally, file_paths.xml follows:
    Code (Text):
    1.  
    2. <?xml version="1.0" encoding="utf-8"?>
    3. <paths xmlns:android="http://schemas.android.com/apk/res/android">
    4.     <files-path name="files" path="files/" />
    5. </paths>
    6.  
    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!
     

    Advertisement

  2. Best Answer:
    Post #2 by Deleted User, Aug 8, 2019 (1 points)
  3. Deleted User

    Deleted User Guest

    Your clue to the cause of the crash is this section from the stack trace

    Code (Text):
    1.  
    2. 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
    3. at android.support.v4.content.FileProvider.parsePathStrategy(FileProvider.java:605)
    4. at android.support.v4.content.FileProvider.getPathStrategy(FileProvider.java:579)
    5. at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:417)
    6. at com.example.sprite.half_lifetimer.ExportDatabase.shareJSON(ExportDatabase.java:109)
    7.  
    This tells you the exception that crashed your app, and the line in your code which caused it.

    So Googling around that error "Attempt to invoke virtual method 'android.content.res.XmlResourceParser ", turns up this link on StackOverflow, amongst others

    https://stackoverflow.com/questions...-to-invoke-xmlresourceparser-on-a-null-string
     
    GameTheory likes this.
Loading...

Share This Page

Loading...