Руководство разработчика

Руководство по интеграции Android Deeplink

X-Installer предоставляет надёжный протокол deeplink, позволяющий сторонним Android-приложениям беспрепятственно запускать установку сложных форматов split-APK без необходимости root-доступа.

Обзор протокола

Схема Deeplinkxinstaller://install?uri=<content_uri>
Целевой пакетcom.pasta.xinstaller
РасширениеОписаниеОбработчик
.apkСтандартный пакет AndroidСистемный по умолчанию
.xapkSplit APK с данными OBBX-Installer
.apksAndroid App Bundle / экспорт AABX-Installer
.apkmSplit-форматы APKMirrorX-Installer
.zipZIP-архив, содержащий файлы APKX-Installer

Настройка окружения

Для безопасной передачи больших файлов APK/XAPK в X-Installer без возникновения FileUriExposedException на Android 7.0+ необходимо реализовать FileProvider.

1. Добавить зависимость

gradle
// File: app/build.gradle
dependencies {
    // Required for FileProvider implementation
    implementation 'androidx.core:core:1.10.1'
}

2. Зарегистрировать FileProvider

xml
<!-- File: AndroidManifest.xml -->
<application>
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>
</application>

3. Определить пути к файлам

xml
<?xml version="1.0" encoding="utf-8"?>
<!-- File: res/xml/file_paths.xml -->
<paths>
    <cache-path name="cache" path="" />
    <files-path name="files" path="" />
</paths>

Основной класс интеграции (Kotlin)

Скопируйте этот вспомогательный класс непосредственно в свой проект. Он обеспечивает определение формата, преобразование URI, предоставление разрешений и переадресацию в Google Play, если пользователь ещё не установил X-Installer.

kotlin
// File: app/src/main/java/com/yourdomain/utils/XInstallerHelper.kt
package com.yourdomain.utils

import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import androidx.appcompat.app.AlertDialog
import androidx.core.content.FileProvider
import java.io.File

class XInstallerHelper(private val context: Context) {

    companion object {
        // Official X-Installer package name
        private const val XINSTALLER_PACKAGE = "com.pasta.xinstaller"
    }

    /**
     * Entry point: Automatically routes the file to the correct installer based on extension.
     */
    fun handleFileInstall(file: File) {
        if (!file.exists() || !file.canRead()) return

        when (file.extension.lowercase()) {
            "apk" -> installApkDirectly(file)
            "xapk", "apks", "apkm", "zip" -> installViaXInstaller(file)
        }
    }

    private fun installViaXInstaller(file: File) {
        if (!isXInstallerInstalled()) {
            showDownloadFallback()
            return
        }

        val contentUri = createContentUri(file) ?: return

        try {
            // 1. Grant temporary read permission to X-Installer
            context.grantUriPermission(
                XINSTALLER_PACKAGE,
                contentUri,
                Intent.FLAG_GRANT_READ_URI_PERMISSION
            )

            // 2. Build the official deeplink protocol
            val deeplink = Uri.Builder()
                .scheme("xinstaller")
                .authority("install")
                .appendQueryParameter("uri", contentUri.toString())
                .build()

            // 3. Launch the intent
            val intent = Intent(Intent.ACTION_VIEW, deeplink).apply {
                flags = Intent.FLAG_ACTIVITY_NEW_TASK
                addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
                setPackage(XINSTALLER_PACKAGE)
            }
            context.startActivity(intent)

        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    private fun installApkDirectly(file: File) {
        val uri = createContentUri(file) ?: return
        val intent = Intent(Intent.ACTION_VIEW).apply {
            setDataAndType(uri, "application/vnd.android.package-archive")
            flags = Intent.FLAG_ACTIVITY_NEW_TASK
            addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        }
        context.startActivity(intent)
    }

    private fun isXInstallerInstalled(): Boolean {
        return try {
            context.packageManager.getPackageInfo(XINSTALLER_PACKAGE, 0)
            true
        } catch (e: PackageManager.NameNotFoundException) {
            false
        }
    }

    private fun createContentUri(file: File): Uri? {
        return try {
            val authority = "${context.packageName}.fileprovider"
            FileProvider.getUriForFile(context, authority, file)
        } catch (e: Exception) {
            null
        }
    }

    private fun showDownloadFallback() {
        AlertDialog.Builder(context)
            .setTitle("X-Installer Required")
            .setMessage("Installing this split APK format requires the official X-Installer. Would you like to download it now?")
            .setPositiveButton("Download from Google Play") { _, _ ->
                val intent = Intent(Intent.ACTION_VIEW).apply {
                    data = Uri.parse("https://play.google.com/store/apps/details?id=$XINSTALLER_PACKAGE")
                }
                context.startActivity(intent)
            }
            .setNegativeButton("Cancel", null)
            .show()
    }
}

Пример использования

После добавления вспомогательного класса вы можете запустить установку из любого Activity или Fragment после завершения загрузки файла.

kotlin
// File: app/src/main/java/com/yourdomain/ui/MainActivity.kt

// Example invocation inside your download completion listener
val installerHelper = XInstallerHelper(this)
val downloadedFile = File(cacheDir, "awesome_game.xapk")

installerHelper.handleFileInstall(downloadedFile)

Нужна помощь?

Для получения последних обновлений, информации о поддержке форматов и продвинутых методах интеграции свяжитесь с нашей командой.

support@xapksinstaller.com