skip to Main Content

I’ m trying to create a temporary file and share it.
So I created this class:

public class GenerateFile {

    public static File writeToFile(Context mcoContext, String sBody) {

        String fileName = "LOG FILE_" + String.valueOf(System.currentTimeMillis()) +".txt";
        File file = new File(mcoContext.getCacheDir(), fileName);

        try{
            FileWriter writer = new FileWriter(file);
            writer.append(sBody);
            writer.flush();
            writer.close();
            return  file;

        }catch (Exception e){
            Toast.makeText(mcoContext, "File write failed: " + e.toString(), Toast.LENGTH_LONG).show();
        }
        return null;
    }
}

to generate a file that after I will share here:

String logContent = "123";
File filePath = new File(file.getAbsolutePath(), "external_files");
filePath.mkdir();
Uri uri = FileProvider.getUriForFile(StatusActivity.this, getPackageName(), filePath);

Intent intent = ShareCompat.IntentBuilder.from(StatusActivity.this)
       .setStream(uri) // uri from FileProvider
        .setType("text/html")
        .getIntent()
        .setAction(Intent.ACTION_VIEW) //Change if needed
        .setDataAndType(uri, "text/*")
        .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);

And in the manifest there are already this permission:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="com.sec.android.provider.badge.permission.WRITE"/>
<uses-permission android:name="com.sec.android.provider.badge.permission.READ"/>

and the provider declaration

 <provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="android.getqardio.com.gmslocationtest"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths"/>
</provider>

The provider_paths class is defined in this way:

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <files-path
        name="share"
        path="external_files"/>
</paths>

But it generate the message, when I try to share it by mail or telegram “Unable to attach file” or “Unsupported attachment”. Also it seems to me that the file is not created.

3

Answers


  1. Chosen as BEST ANSWER

    So I follow the suggestion of @CommonsWare, and I edited my code. This is the final result:

    public class GenerateFile {
    
        public static Uri getFileURI(Context context, String nameFile, String content, String fileExtension) {
            DateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd");
            Date date = new Date();
            String fileName = dateFormat.format(date)+nameFile+fileExtension;
            File file = new File(context.getCacheDir(), fileName);
    
            try{
                FileWriter writer = new FileWriter(file);
                writer.append(content);
                writer.flush();
                writer.close();
                //Toast.makeText(context, "Writing to the file completed successfully", Toast.LENGTH_LONG).show();
            }catch (Exception e){
                Toast.makeText(context, "File writing failed: " + e.toString(), Toast.LENGTH_LONG).show();
            }
    
            File filePath = new File(context.getCacheDir(), "");
            File newFile = new File(filePath, fileName);
            return FileProvider.getUriForFile(context, "MYPACKAGE.fileprovider", newFile);
        }
    }
    

    and in another class:

    private void sendFile(String nameFile, String logContent,  String fileExtension) {
            Uri contentUri = GenerateFile.getFileURI(getApplicationContext(), nameFile, logContent, fileExtension);
    
            Intent intent = ShareCompat.IntentBuilder.from(StatusActivity.this)
                    .setStream(contentUri) // uri from FileProvider
                    .setType("text/plain")
                    .getIntent()
                    .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            startActivity(Intent.createChooser(intent, "send"));
    }
    

    so to send the file. I also deleted the permission (previously mentioned) in the manifest, because I didn't need it anymore.

    And I also edited my provider and provider_path file like that:

    <provider
       android:name="android.support.v4.content.FileProvider"
       android:authorities="MYPACKAGE.fileprovider"
       android:exported="false"
       android:grantUriPermissions="true">
       <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths" />
     </provider>
    
    <?xml version="1.0" encoding="utf-8"?>
    <cache-path
        name="my_files"
        path=""
    />
    

    Now it works! Thank you very much guys for the help!


  2. Did you specifically ask the user for those permissions? It’s not enough to just put the permissions in the manifest for target sdks below 28. Also, in Android Q, you will need to work around external storage permissions altogether as this is disallowed.

    Login or Signup to reply.
  3. Other apps do not have access to your app’s getCacheDir(). FLAG_GRANT_READ_URI_PERMISSION and FLAG_GRANT_WRITE_URI_PERMISSION are for content Uri values, not file Uri values. And, on Android 7.0+ devices, your code should crash with a FileUriExposedException.

    Use FileProvider to make your content available to other apps, and use FileProvider.getUriForFile() to get the Uri to put in the Intent.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search