TomB
TomB

Reputation: 760

Delphi: Null pointer on TJFileProvider.JavaClass.getUriForFile

I have a Delphi 10.3.3 Android app which can download a replacement APK and (in Android 6-) can install it successfully.

I have adapted that code for Android 7+ (based largely on an answer on SO). For clarity for this exercise, I have put the Android 7+ code into its own procedure as below. However, I get an exception on the getURIforFile():

java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.PackageItemInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference

I have checked "Secure File Sharing" in the Entitlements List, and the expected provider section is in the manifest generated by Delphi:

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

The provider-paths.xml is generated and is included in the deployment.

I have confirmed that the file parameter (AFilename) does indeed exist when this is called.

This is the code below (all wrapped in try..except to catch the error):

procedure TmyForm.StartActivityA24(const AFileName: string);
var
  Intent: JIntent;
  Data: Jnet_Uri;
  lFile: JFile;
begin
  try
    Intent := TJIntent.Create;
    Intent.setAction(TJIntent.JavaClass.ACTION_VIEW);
    lFile := TJFile.JavaClass.init(StringToJString(AFileName));
    // I've confirmed previously that the file exists
    Intent.setFlags(TJIntent.JavaClass.FLAG_GRANT_READ_URI_PERMISSION);
    // this is the problem line (so far)
    Data := TJFileProvider.JavaClass.getUriForFile(TAndroidHelper.Context,
      StringToJString('com.embarcadero.myappname.fileprovider'), lFile);
    Intent.setDataAndType(Data, StringToJString('application/vnd.android.package-archive'));
    
    TAndroidHelper.Activity.startActivity(Intent);
  except
    on E: Exception do
    begin
      DoMsgConfirm('Exception on Install. Msg=' + slinebreak + e.message, nil, nil, 'excption', lyCurrentPage, blureffect1, false );
    end;
  end;
end;

Upvotes: 1

Views: 1246

Answers (1)

TomB
TomB

Reputation: 760

I changed the line:

StringToJString('com.embarcadero.myapp.fileprovider'), lFile);

to the more generic:

StringToJString(JStringToString(TAndroidHelper.Context.getApplicationContext.getPackageName) + '.fileprovider'), lFile);

I would have thought they evaluated to the same thing. But now it proceeds in to the install.

After the install is complete it does not come to the foreground however (as it did in android 6). Maybe I have to add something like this (after the initial setflags):

Intent.addFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK);

Inspired guesswork! That worked.

Upvotes: 1

Related Questions