Jump to content
pcplayer99

Android, how to call a TJIntent

Recommended Posts

On Android 6, I can play MP4 by call TJIntent:

 

    uri := StrToJURI('file://' + AURI);

    Intent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_VIEW);
    intent.setDataAndType(uri, StringToJstring('video/mp4'));
    TAndroidHelper.Activity.startActivity(Intent); 

 

On Android 9, there is a exception:

raised exception class EJNIException with message 'android.os.FileUriExposedException: file:///storage/emulated/0/Download/VIDOES/4114049.mp4 exposed beyond app through Intent.getData()

 

I have googled on Internet, it must use file provider. There is a demo code in:  https://community.idera.com/developer-tools/platforms/f/android-platform/68376/my-apps-autoupdate-not-working-rio-10-3-1-tokyo-10-2-3-working

 

and in this link: https://www.delphiworlds.com/2018/06/targeting-android-8-and-higher-continued/  it is said that we need add some provider code into AndroidManifest.template.

 

So, I write code like this:

 

AJavaFile := TJFile.JavaClass.init(StringToJstring( AURI));
uri := TAndroidHelper.JFileToJURI(AJavaFile);   

 

and update AndroidManifest.template file add some code in it:

 

<application android:persistent="%persistent%" 
        android:restoreAnyVersion="%restoreAnyVersion%" 
        android:label="%label%" 
        android:debuggable="%debuggable%" 
        android:largeHeap="%largeHeap%"
        android:icon="%icon%"
        android:theme="%theme%"
        android:hardwareAccelerated="%hardwareAccelerated%"
        android:resizeableActivity="false">

         <%provider%>
		
		<provider
          android:name="android.support.v4.content.FileProvider"
          android:authorities="com.embarcadero.firemonkey.fileprovider"
          android:exported="false"
          android:grantUriPermissions="true">
          <meta-data android:name="android.support.FILE_PROVIDER_PATHS" 
		  android:resource="@xml/provider_paths"/>  
        </provider>   
		
        <%application-meta-data%>
        <%services%>
        <!-- Our activity is a subclass of the built-in NativeActivity framework class.
             This will take care of integrating with our NDK code. -->
        <activity android:name="com.embarcadero.firemonkey.FMXNativeActivity"
                android:label="%activityLabel%"
                android:configChanges="orientation|keyboard|keyboardHidden|screenSize"
                android:launchMode="singleTask">
            <!-- Tell NativeActivity the name of our .so -->
            <meta-data android:name="android.app.lib_name"
                android:value="%libNameValue%" />
            <intent-filter>  
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter> 
        </activity>
        <%activity%>
        <%receivers%>
    </application>

 

another XML file is provider_paths.xml, like this:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>

 

but when call "uri := TAndroidHelper.JFileToJURI(AJavaFile); " there is a exception: 

raised exception class EJNIException with message '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'.

 

So, is there a demo that how to call a TJIntent on Android 7 or higher version?

 

 

Share this post


Link to post

If you are using Delphi 10.3, for this situation you do not need to modify AndroidManifest.template.xml yourself. Unless you have other customizations to it, please delete it (or remove your <provider> changes). 

 

Go to the Project Options, select Application > Entitlement List and check the Secure File Sharing checkbox.

Share this post


Link to post

Thank you Dave.

 

I have tested, checked Secure File Sharing, and the exception is still raising.

Edited by pcplayer99

Share this post


Link to post

I update my code from uri := StrToJURI('file://' + AURI);

to:

 

LUri := TAndroidHelper.JFileToJURI(TJFile.JavaClass.init(StringToJString(AFileName)));

 

and it works.

 

Thanks Dave.

  • Like 1

Share this post


Link to post

Hello,

 

I have problem to add <provider> to my AndroidManifest.template.xml Rad Studio 10.3.2.

 

I'm try  delete AndroidManifest.template.xml and go to Project Options, select Application > Entitlement List and check the Secure File Sharing checkbox.

 

But in  AndroidManifest.template.xml  not generate provider code.... Also I'm clear project but again not generate tag any other solution?

Share this post


Link to post
3 hours ago, Alex Texera said:

Hello,

 

I have problem to add <provider> to my AndroidManifest.template.xml Rad Studio 10.3.2.

 

I'm try  delete AndroidManifest.template.xml and go to Project Options, select Application > Entitlement List and check the Secure File Sharing checkbox.

 

But in  AndroidManifest.template.xml  not generate provider code.... Also I'm clear project but again not generate tag any other solution?

Solution:

 

I always must put manual provider code in AndroidManfisest.templete in Relase folder before deployment.   After build provider code is deleted. Secure file sharing is checked. In other project don't have this problem. What kill provider code I don't know.

Edited by Alex Texera

Share this post


Link to post
9 hours ago, Alex Texera said:

What kill provider code I don't know.

Check the file AndroidManifest.xml in the folder: C:\Users\(username)\AppData\Roaming\Embarcadero\BDS\20.0

 

Where (username) is your logged in Windows username. This is the file that the IDE uses for AndroidManifest.template.xml. Part of the file should look like this:

 

        <%provider%>
        <%application-meta-data%>
        <%uses-libraries%>
        <%services%>

 

  • Like 1

Share this post


Link to post
On 10/25/2019 at 11:25 PM, Dave Nottage said:

Check the file AndroidManifest.xml in the folder: C:\Users\(username)\AppData\Roaming\Embarcadero\BDS\20.0

 

Where (username) is your logged in Windows username. This is the file that the IDE uses for AndroidManifest.template.xml. Part of the file should look like this:

 

        <%provider%>
        <%application-meta-data%>
        <%uses-libraries%>
        <%services%>

 

In this  AndroidManifest.xml in the folder: C:\Users\(username)\AppData\Roaming\Embarcadero\BDS\20.0  i have:

 

        <%provider%>
        <%application-meta-data%>
        <%uses-libraries%>
        <%services%>

 

 

For some project eg. new blank project all work fine but in my other project after release provider tag is deleted.

manifest.jpg

Edited by Alex Texera

Share this post


Link to post
7 hours ago, Alex Texera said:

in my other project after release provider tag is deleted.

On deployment, the <%provider%> tag is either replaced with provider information for secure file sharing, e.g:

 

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

 

or it is simply removed. If you're expecting the former, please ensure that you have Secure File Sharing checked in the Entitlements section of Project Options for the configuration you are building for (i.e. Debug and/or Release)

Share this post


Link to post

What Dave Nottage excludes completely is the fact that during creation the AndroidManifest.xml is copied to AndroidManifest.template.xml in your source directory.

 

So changing the AndroidManifest.xml in your AppData folder has zero effect if there already is a AndroidManifest.template.xml present.

 

Make any changes you need to the AndroidManifest.template.xml because that file will be used to create the AndroidManifest.xml in the apk.

 

This is what made me realize that people were talking about the wrong file origin: http://docwiki.embarcadero.com/RADStudio/Rio/en/Preparing_an_Android_Application_for_Deployment

Share this post


Link to post
3 hours ago, BobTheBuilder said:

What Dave Nottage excludes completely is the fact that during creation the AndroidManifest.xml is copied to AndroidManifest.template.xml in your source directory.

You're misrepresenting my reply. It is exactly why I said to examine that file.

 

3 hours ago, BobTheBuilder said:

So changing the AndroidManifest.xml in your AppData folder has zero effect

It certainly does have an effect when creating new projects.

Share this post


Link to post
On 7/29/2019 at 5:09 AM, Dave Nottage said:

Go to the Project Options, select Application > Entitlement List and check the Secure File Sharing checkbox.

This is a two-year old post but I just want to say a big THANK YOU for this answer. I spent the better part of a day in anguish over this very problem where a demo program worked just fine but copying the code to my program did not. After comparing everything between the two projects and hunting around the internet for possible answers, I finally found this and it was solved immediately!

  • Like 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×