Reputation: 760
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
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