Skip to content

Material Files

There are notes from my attempt to learn android development with kotlin using MaterialFiles by zhanghai project as a reference:

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>

<!--
  ~ Copyright (c) 2018 Hai Zhang <dreaming.in.code.zh@gmail.com>
  ~ All Rights Reserved.
  -->

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

    <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
    <uses-feature android:name="android.hardware.wifi" android:required="false" />
    <uses-feature android:name="android.software.leanback" android:required="false" />

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission
        android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
        tools:ignore="ScopedStorage" />
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    <uses-permission
        android:name="android.permission.QUERY_ALL_PACKAGES"
        tools:ignore="QueryAllPackagesPermission" />
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="32" />
    <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />

    <!-- Shizuku requires API 23. -->
    <uses-sdk tools:overrideLibrary="rikka.shizuku.aidl,rikka.shizuku.api,rikka.shizuku.shared" />

    <!--
      ~ Samsung DeX requires explicitly setting android:resizeableActivity="true" for the app to be
      ~ resizable.
      ~ TODO: Remove this attribute once Samsung respects the default value for it.
      -->
    <application
        android:allowBackup="true"
        android:banner="@drawable/banner"
        android:enableOnBackInvokedCallback="true"
        android:fullBackupContent="true"
        android:icon="@mipmap/launcher_icon"
        android:label="@string/app_name"
        android:networkSecurityConfig="@xml/netework_security_config"
        android:requestLegacyExternalStorage="true"
        android:requestRawExternalStorageAccess="true"
        android:resizeableActivity="true"
        android:roundIcon="@mipmap/launcher_icon"
        android:supportsRtl="true"
        android:theme="@style/Theme.MaterialFiles"
        android:usesCleartextTraffic="true"
        tools:ignore="GoogleAppIndexingWarning,UnusedAttribute">

        <activity
            android:name="me.zhanghai.android.files.filelist.FileListActivity"
            android:exported="true"
            android:visibleToInstantApps="true"
            tools:ignore="UnusedAttribute">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
                <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
            </intent-filter>
            <intent-filter tools:ignore="AppLinkUrlError">
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="inode/directory" />
                <data android:mimeType="resource/folder" />
                <data android:mimeType="vnd.android.document/directory" />
            </intent-filter>
            <!-- @see me.zhanghai.android.files.file.isSupportedArchive -->
            <intent-filter
                android:label="@string/archive_viewer_title"
                tools:ignore="AppLinkUrlError">
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="application/gzip" />
                <data android:mimeType="application/java-archive" />
                <data android:mimeType="application/rar" />
                <data android:mimeType="application/zip" />
                <data android:mimeType="application/zstd" />
                <data android:mimeType="application/vnd.android.package-archive" />
                <data android:mimeType="application/vnd.debian.binary-package" />
                <data android:mimeType="application/vnd.ms-cab-compressed" />
                <data android:mimeType="application/vnd.rar" />
                <data android:mimeType="application/x-bzip2" />
                <data android:mimeType="application/x-compress" />
                <data android:mimeType="application/x-cpio" />
                <data android:mimeType="application/x-deb" />
                <data android:mimeType="application/x-debian-package" />
                <data android:mimeType="application/x-gtar" />
                <data android:mimeType="application/x-gtar-compressed" />
                <data android:mimeType="application/x-java-archive" />
                <data android:mimeType="application/x-lzma" />
                <data android:mimeType="application/x-tar" />
                <data android:mimeType="application/x-xz" />
                <data android:mimeType="application/x-7z-compressed" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.GET_CONTENT" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.OPENABLE" />
                <data android:mimeType="*/*" />
            </intent-filter>
            <!-- @see https://android.googlesource.com/platform/packages/apps/DocumentsUI/+/main/AndroidManifest.xml -->
            <intent-filter>
                <action android:name="android.intent.action.OPEN_DOCUMENT" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.OPENABLE" />
                <data android:mimeType="*/*" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.CREATE_DOCUMENT" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.OPENABLE" />
                <data android:mimeType="*/*" />
            </intent-filter>
            <!--
              ~ Unusable until we implement DocumentsProvider.
            <intent-filter>
                <action android:name="android.intent.action.OPEN_DOCUMENT_TREE" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
            -->
            <intent-filter>
                <action android:name="me.zhanghai.android.files.intent.action.VIEW_DOWNLOADS" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
            <meta-data
                android:name="android.app.shortcuts"
                android:resource="@xml/shortcuts" />
        </activity>

        <!--
          ~ Using android:documentLaunchMode="always" gives a better result than
          ~ Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK. Not sure why though.
          -->
        <activity
            android:name="me.zhanghai.android.files.filelist.OpenFileActivity"
            android:documentLaunchMode="always"
            android:excludeFromRecents="true"
            android:exported="true"
            android:theme="@style/Theme.MaterialFiles.Translucent">
            <intent-filter>
                <action android:name="me.zhanghai.android.files.intent.action.OPEN_FILE" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="*/*" />
            </intent-filter>
        </activity>

        <activity
            android:name="me.zhanghai.android.files.filelist.EditFileActivity"
            android:autoRemoveFromRecents="true"
            android:icon="@drawable/edit_icon"
            android:label="@string/file_edit_title"
            android:theme="@style/Theme.MaterialFiles.Translucent" />

        <activity
            android:name="me.zhanghai.android.files.filelist.OpenFileAsDialogActivity"
            android:autoRemoveFromRecents="true"
            android:icon="@drawable/open_as_icon"
            android:label="@string/file_open_as_title"
            android:theme="@style/Theme.MaterialFiles.Translucent" />

        <activity
            android:name="me.zhanghai.android.files.storage.AddStorageDialogActivity"
            android:label="@string/storage_add_storage_title"
            android:theme="@style/Theme.MaterialFiles.Translucent" />

        <activity
            android:name="me.zhanghai.android.files.storage.EditDeviceStorageDialogActivity"
            android:label="@string/storage_edit_device_storage_title"
            android:theme="@style/Theme.MaterialFiles.Translucent" />

        <activity
            android:name="me.zhanghai.android.files.storage.AddExternalStorageShortcutActivity"
            android:label="@string/storage_add_external_storage_shortcut_title"
            android:theme="@style/Theme.MaterialFiles.Translucent" />

        <activity
            android:name="me.zhanghai.android.files.storage.EditExternalStorageShortcutDialogActivity"
            android:label="@string/storage_edit_external_storage_shortcut_title"
            android:theme="@style/Theme.MaterialFiles.Translucent" />

        <activity
            android:name="me.zhanghai.android.files.storage.AddDocumentTreeActivity"
            android:label="@string/storage_add_document_tree_title"
            android:theme="@style/Theme.MaterialFiles.Translucent" />

        <activity
            android:name="me.zhanghai.android.files.storage.EditDocumentTreeDialogActivity"
            android:label="@string/storage_edit_document_tree_title"
            android:theme="@style/Theme.MaterialFiles.Translucent" />

        <activity
            android:name="me.zhanghai.android.files.storage.EditFtpServerActivity"
            android:label="@string/storage_edit_ftp_server_title_edit"
            android:theme="@style/Theme.MaterialFiles" />

        <activity
            android:name="me.zhanghai.android.files.storage.EditSftpServerActivity"
            android:label="@string/storage_edit_sftp_server_title_edit"
            android:theme="@style/Theme.MaterialFiles" />

        <activity
            android:name="me.zhanghai.android.files.storage.AddLanSmbServerActivity"
            android:label="@string/storage_add_lan_smb_server_title"
            android:theme="@style/Theme.MaterialFiles" />

        <activity
            android:name="me.zhanghai.android.files.storage.EditSmbServerActivity"
            android:label="@string/storage_edit_smb_server_title_edit"
            android:theme="@style/Theme.MaterialFiles" />

        <activity
            android:name="me.zhanghai.android.files.storage.EditWebDavServerActivity"
            android:label="@string/storage_edit_webdav_server_title_edit"
            android:theme="@style/Theme.MaterialFiles" />

        <activity
            android:name="me.zhanghai.android.files.navigation.EditBookmarkDirectoryDialogActivity"
            android:label="@string/navigation_edit_bookmark_directory_title"
            android:theme="@style/Theme.MaterialFiles.Translucent" />

        <activity
            android:name="me.zhanghai.android.files.ftpserver.FtpServerActivity"
            android:exported="true"
            android:label="@string/ftp_server_title"
            android:launchMode="singleTop"
            android:theme="@style/Theme.MaterialFiles">
            <intent-filter>
                <action android:name="me.zhanghai.android.files.intent.action.MANAGE_FTP_SERVER" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

        <activity
            android:name="me.zhanghai.android.files.settings.SettingsActivity"
            android:exported="true"
            android:label="@string/settings_title"
            android:launchMode="singleTop"
            android:theme="@style/Theme.MaterialFiles">
            <intent-filter>
                <action android:name="android.intent.action.APPLICATION_PREFERENCES" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

        <activity
            android:name="me.zhanghai.android.files.storage.StorageListActivity"
            android:label="@string/storage_list_title"
            android:launchMode="singleTop"
            android:theme="@style/Theme.MaterialFiles" />

        <activity
            android:name="me.zhanghai.android.files.settings.StandardDirectoryListActivity"
            android:label="@string/settings_standard_directory_list_title"
            android:launchMode="singleTop"
            android:theme="@style/Theme.MaterialFiles" />

        <activity
            android:name="me.zhanghai.android.files.settings.BookmarkDirectoryListActivity"
            android:label="@string/settings_bookmark_directory_list_title"
            android:launchMode="singleTop"
            android:theme="@style/Theme.MaterialFiles" />

        <activity
            android:name="me.zhanghai.android.files.about.AboutActivity"
            android:label="@string/about_title"
            android:launchMode="singleTop"
            android:theme="@style/Theme.MaterialFiles" />

        <activity
            android:name="me.zhanghai.android.files.fileaction.ArchivePasswordDialogActivity"
            android:autoRemoveFromRecents="true"
            android:theme="@style/Theme.MaterialFiles.Translucent" />

        <activity
            android:name="me.zhanghai.android.files.filejob.FileJobErrorDialogActivity"
            android:autoRemoveFromRecents="true"
            android:theme="@style/Theme.MaterialFiles.Translucent" />

        <activity
            android:name="me.zhanghai.android.files.filejob.FileJobConflictDialogActivity"
            android:autoRemoveFromRecents="true"
            android:theme="@style/Theme.MaterialFiles.Translucent" />

        <activity
            android:name="me.zhanghai.android.files.viewer.saveas.SaveAsActivity"
            android:autoRemoveFromRecents="true"
            android:exported="true"
            android:label="@string/save_as_title"
            android:theme="@style/Theme.MaterialFiles.Translucent">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <data
                    android:mimeType="*/*"
                    android:scheme="content" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.SEND" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="*/*" />
            </intent-filter>
        </activity>

        <activity
            android:name="me.zhanghai.android.files.viewer.text.TextEditorActivity"
            android:exported="true"
            android:label="@string/text_editor_title"
            android:theme="@style/Theme.MaterialFiles">
            <intent-filter tools:ignore="AppLinkUrlError">
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="application/ecmascript" />
                <data android:mimeType="application/javascript" />
                <data android:mimeType="application/json" />
                <data android:mimeType="application/typescript" />
                <data android:mimeType="application/x-sh" />
                <data android:mimeType="application/x-shellscript" />
                <data android:mimeType="application/xml" />
                <data android:mimeType="application/yaml" />
                <data android:mimeType="text/*" />
            </intent-filter>
        </activity>

        <activity
            android:name="me.zhanghai.android.files.viewer.image.ImageViewerActivity"
            android:exported="true"
            android:label="@string/image_viewer_title"
            android:theme="@style/Theme.MaterialFiles.Immersive">
            <intent-filter tools:ignore="AppLinkUrlError">
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="image/*" />
            </intent-filter>
        </activity>

        <service
            android:name="me.zhanghai.android.files.filejob.FileJobService"
            android:foregroundServiceType="dataSync" />

        <service android:name="me.zhanghai.android.files.ftpserver.FtpServerService"
            android:foregroundServiceType="dataSync" />

        <service
            android:name="me.zhanghai.android.files.ftpserver.FtpServerTileService"
            android:exported="true"
            android:icon="@drawable/shared_directory_icon_white_24dp"
            android:label="@string/ftp_server_title"
            android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
            tools:ignore="NewApi">
            <intent-filter>
                <action android:name="android.service.quicksettings.action.QS_TILE"/>
            </intent-filter>
            <meta-data
                android:name="android.service.quicksettings.TOGGLEABLE_TILE"
                android:value="true" />
        </service>

        <service
            android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
            android:enabled="false"
            android:exported="false">
            <meta-data
                android:name="autoStoreLocales"
                android:value="true" />
        </service>

        <provider
            android:name="me.zhanghai.android.files.app.AppProvider"
            android:authorities="@string/app_provider_authority"
            android:exported="false" />

        <provider
            android:name="me.zhanghai.android.files.file.FileProvider"
            android:authorities="@string/file_provider_authority"
            android:exported="false"
            android:grantUriPermissions="true" />

        <receiver android:name="me.zhanghai.android.files.filejob.FileJobReceiver" />

        <receiver android:name="me.zhanghai.android.files.ftpserver.FtpServerReceiver" />

        <meta-data
            android:name="firebase_crashlytics_collection_enabled"
            android:value="false" />
    </application>
</manifest>

Comments