Our general problem is we need our app in a tablet to send a mail to another tablet where our app reads one attachment file, in HTML.
But because of "security" we cannot manipulate the mail app as an Intent object, and we cannot simply scan the Downloads folder looking for the attachment.
So let's try to register a file mimeType, so at least the user can tap on the file in the Downloads folder, and pick our app in the Intent chooser.
Start by telling AndroidManifest.xml that our app is allowed to read files, just like every other program since the dawn of computing:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
Note those are mostly deprecated (for Android 14), and note that the modern replacements, such as READ_MEDIA_IMAGES, seem to refer to civilians playing with their camera rolls, and there's no READ_MEDIA_TEXT or READ_MEDIA_HTML.
Now tell the Manifest that our app is always unique and top-level:
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize|keyboard|keyboardHidden|navigation"
android:theme="@style/AppTheme.NoActionBar"
android:screenOrientation="sensorLandscape"
tools:ignore="LockedOrientationActivity"
android:foregroundServiceType="location"
android:exported="true"
android:launchMode="singleTop"
>
Now after the first <intent-filter>
(that makes us an app) add another filter that makes us into a mimeType handler:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file" />
<data android:host="*" />
<data android:mimeType="text/html" />
<data android:pathPattern=".*\\.html" />
</intent-filter>
Now add to MainActivity.java a handler to receive the Intent:
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (intent != null && Intent.ACTION_VIEW.equals(intent.getAction())) {
Uri fileUri = intent.getData();
if (fileUri != null) {
Log.e("TODO", "yo: " + fileUri);
setGreenStatusBar(fileUri.getPath());
}
}
}
Okay, now we mail a File.html attachment to the tablet, download it to the Downloads folder, and tap on it. We get only the default HTML mimeType handlers - Chrome, HTML Viewer, and Internet.
So how can we get our app to open a file found in the Downloads folder?
Replace:
<data android:scheme="file" />
<data android:host="*" />
<data android:mimeType="text/html" />
<data android:pathPattern=".*\\.html" />
with:
<data android:scheme="content" />
<data android:mimeType="text/html" />
The file
scheme largely was abandoned several years ago.
Start by telling AndroidManifest.xml that our app is allowed to read files
You will not need any of those. Two of them (the INTERNAL
ones) do not even exist. Use ContentResolver
and openInputStream()
to get an InputStream
on the content identified by the Uri
that you will receive either in onCreate()
(if the activity is being created new) or onNewIntent()
(if the activity already existed and is getting a new Intent
delivered to it).
android:foregroundServiceType="location"
This is for services. It is pointless for an <activity>
.