• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
Locked
0

Problems getting FileProvider and ContentProviders working in Flex Native Extensions.

Guest
Nov 01, 2013 Nov 01, 2013

Copy link to clipboard

Copied

As part of an Adobe Flex application, I am writing an android native extension to allow me to send emails with file attachments using files generated from flex code. However I don't want the file to be world readable as it might contain sensitive data. Therefore I want to send the file from within my app's internal storage area / cache. I am using Intents to communicate with other apps (such as Gmail) to send the email.

After doing some research, I discovered that the functionality of FileProviders should do exactly what I want. However the static method **FileProvider.getUriForFile()** is silently failing / crashing the native extension. The native extension stops and returns null with no errors or output from LogCat.

If I manually create the Uri by parsing a string, Gmail complains that it can't attach the file to the email, and the email is sent with no attachment.

Code in FREObject call():

    //... (Deal with params from flex app) ...

   

    //Setup Intent, and attach email data send from flex application:

    Intent intent = new Intent(Intent.ACTION_SEND);

    intent.setType("message/rfc822");

    intent.putExtra(Intent.EXTRA_EMAIL, toArray);

    intent.putExtra(Intent.EXTRA_CC, ccArray);

    intent.putExtra(Intent.EXTRA_BCC, bccArray);

    intent.putExtra(Intent.EXTRA_SUBJECT, subject);

    intent.putExtra(Intent.EXTRA_TEXT, message);

   

    Log.d("emaildebug", filePath);

    //Check we can read our email attachment from flex app

    //filePath is a temporary cache location.

    File appFile = new File(filePath);

    if (appFile.exists() && appFile.canRead()) {

        Log.d("emaildebug", "file successfully read");

    } else {

        return null;

    }

    //Get a handle on the android Context instead of FREContext.

    Context androidContext = (Context) context.getActivity();

   

    //Get the location of the root files directory.

    File attachPath = androidContext.getFilesDir();

    File attachFile = new File(attachPath, "attachment.pdf");

   

    //Copy file to root of files directory, so that our FileProvider can access it.

    try {

        copyFileUsingChannel(appFile, attachFile);

    } catch (Exception e) {

        Log.d("emaildebug", e.getMessage());

    }

   

    Log.d("emaildebug", "attachFile exists: " + attachFile.exists() );

    Log.d("emaildebug", "attachFile path: " + attachFile.getAbsolutePath());

   

    //This line will silently crash the native extension, instantly returning null, even in try catch.

    //Uri contentUri = FileProvider.getUriForFile(androidContext, "com.example.androidextensiontest.provider", attachFile);

   

    //Therefore manually create the Uri from a string.

    Uri contentUri = Uri.parse("content://com.example.androidextensiontest.provider/files/attachment.pdf");

    Log.d("emaildebug", "uri created");

    Log.d("emaildebug", contentUri.toString());

   

    //Grant permisions for all apps that can handle given intent

    //Courtesy of: http://stackoverflow.com/questions/18249007/how-to-use-support-fileprovider-for-sharing-content-to-o...

    List<ResolveInfo> resInfoList = androidContext.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);

    for (ResolveInfo resolveInfo : resInfoList) {

        String packageName = resolveInfo.activityInfo.packageName;

        Log.d("emaildebug", "package: " + packageName);

        androidContext.grantUriPermission(packageName, contentUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);

    }

   

    intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);

    intent.putExtra(Intent.EXTRA_STREAM, contentUri);

    context.getActivity().startActivity(Intent.createChooser(intent, "Send mail using..."));

In Manifest File:

    <provider

        android:name="android.support.v4.content.FileProvider"

        android:authorities="com.example.androidextensiontest.provider"

        android:exported="false"

        android:grantUriPermissions="true" >

        <meta-data

            android:name="android.support.FILE_PROVIDER_PATHS"

            android:resource="@xml/my_paths" />

    </provider>

**In my_paths.xml:**

    <paths xmlns:android="http://schemas.android.com/apk/res/android">

        <files-path name="files" path="." />

    </paths>

LogCat output:

    11-01 10:58:09.971: D/emaildebug(17013): /data/data/air.com.example.MyAppName.debug/cache/FlashTmp.V17013/attachment.pdf

    11-01 10:58:09.971: D/emaildebug(17013): file successfully read

    11-01 10:58:09.991: D/emaildebug(17013): attachFile exists: true

    11-01 10:58:09.991: D/emaildebug(17013): attachFile path: /data/data/air.com.example.MyAppName.debug/files/attachment.pdf

    11-01 10:58:09.991: D/emaildebug(17013): uri created

    11-01 10:58:09.991: D/emaildebug(17013): content://com.example.androidextensiontest.provider/files/attachment.pdf

    11-01 10:58:09.991: D/emaildebug(17013): package: com.android.email

    11-01 10:58:09.991: D/emaildebug(17013): package: com.google.android.gm

If I attempt to send the file from external storage using a file:// Uri, the file attachment works perfectly. However as previously mentioned the file attachment potentially contains sensitive data, therefore I wish to avoid using external storage.

What I believe I'm seeing is that FileProviders do not work within native extensions. I tried also using a ContentProvider, however neither the Constructor nor onCreate methods were called.

ContentProvider Manifest:

    <provider

        android:name="com.example.androidextensiontest.provider.MyContentProvider"

        android:authorities="com.example.androidextensiontest.provider">

    </provider>

MyContentProvider:

    public class MyContentProvider extends ContentProvider implements PipeDataWriter<InputStream> {

    public MyContentProvider() {

        // Never Output

        Log.d("emaildebug", "Constructor");

    }

   

    @Override

    public boolean onCreate() {

        // Never Output

        Log.d("emaildebug", "OnCreate");

        return false;

    }

    //.. Rest of class

    }

Am I doing something wrong or are ContentProviders / FileProviders just not supported within flex native extensions? Alternatively, are there any other solutions for attaching a file located in internal storage to an email. My searching on Stack Overflow and google has not encountered anyone else having similar experiences, especially regarding FileProvider.getUriForFile(). Any help / comments appreciated.

Sorry for the wall of text, I wanted to record everything I've tried so far, and what works and what doesn't.

tldr; Do ContentProviders / File Providers work in flex native extensions? Are there any other methods of sending internal files as email attachments?

Views

3.1K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines