Ошибка в загрузке динамической функции. Комплект приложений Android - PullRequest
0 голосов
/ 28 августа 2018

В Android API level, 26 (Oreo) и выше я получаю эту ошибку. Если я запускаю динамическую функцию из Android Studio прямо на устройство, динамическая функция работает нормально, но когда я загружаю комплект приложений в Play Store и пытаюсь запустить динамическую функцию из приложения, загруженного из Play Store, я получаю

Исключение времени выполнения: ресурсы $ NotFoundException на каждом ресурсе (string.xml, atrr.xml и т. д.).

Ниже уровня Android API, 26 работает нормально.

Журнал ошибок:

2018-08-27 18: 23: 41,097 20926-20926 /? E / AndroidRuntime: FATAL ИСКЛЮЧЕНИЕ: главная Процесс: com.ak.ta.dainikbhaskar.activity.release, PID: 20926 java.lang.RuntimeException: невозможно запустить действие ComponentInfo {com.ak.ta.dainikbhaskar.activity.release / com.dainik.bhaskar.fitness.activities.EntryActivity}: android.content.res.Resources $ NotFoundException: строковый идентификатор ресурса

0x7e0b000e

    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2792)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2870)
    at android.app.ActivityThread.-wrap11(Unknown Source:0)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1601)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:172)
    at android.app.ActivityThread.main(ActivityThread.java:6590)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
 Caused by: android.content.res.Resources$NotFoundException: String resource ID #0x7e0b000e
    at android.content.res.Resources.getText(Resources.java:339)
    at android.content.res.Resources.getString(Resources.java:433)
    at android.content.Context.getString(Context.java:556)
    at com.dainik.bhaskar.fitness.activities.base.BaseActivity.onCreate(BaseActivity.java:34)
    at com.dainik.bhaskar.fitness.activities.EntryActivity.onCreate(EntryActivity.java:31)
    at android.app.Activity.performCreate(Activity.java:7023)
    at android.app.Activity.performCreate(Activity.java:7014)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1215)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2745)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2870)

    at android.app.ActivityThread.-wrap11(Unknown Source:0) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1601) 
    at android.os.Handler.dispatchMessage(Handler.java:106) 
    at android.os.Looper.loop(Looper.java:172) 
    at android.app.ActivityThread.main(ActivityThread.java:6590) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)

    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

код:

открытый класс MainActivity расширяет AppCompatActivity, реализует View.OnClickListener {

SplitInstallManager installManager;
String EpaperModuleName = "epaper_dynamic_lib";
private final String EPaperLauncherclassName = "com.bhaskar.epaper.ui.SplashActivity";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    (findViewById(R.id.btn_epaper)).setOnClickListener(this);
    installManager = SplitInstallManagerFactory.create(this);
    installManager.registerListener(splitInstallStateUpdatedListener);

}


private void loadAndLaunchModule(String moduleName, String launcherclassName) {
    // Skip loading if the module already is installed. Perform success action directly.
    if (installManager.getInstalledModules().contains(moduleName)) {
        Toast.makeText(getApplicationContext(), "onSuccessfulLoad " + moduleName, Toast.LENGTH_LONG).show();
        onSuccessfulLoad(moduleName, launcherclassName, true);
        return;
    }

    // Create request to install a feature module by name.
    SplitInstallRequest request = SplitInstallRequest.newBuilder()
            .addModule(moduleName)
            .build();

    // Load and install the requested feature module.
    installManager.startInstall(request);
    Toast.makeText(getApplicationContext(), "startInstall " + moduleName, Toast.LENGTH_LONG).show();
}

private final SplitInstallStateUpdatedListener splitInstallStateUpdatedListener = new SplitInstallStateUpdatedListener() {
    @Override
    public void onStateUpdate(SplitInstallSessionState splitInstallSessionState) {
        List<String> splitModules = splitInstallSessionState.moduleNames();

        boolean multiInstall = splitModules.size() > 1;
        Toast.makeText(getApplicationContext(), "multiInstall " + multiInstall, Toast.LENGTH_LONG).show();

        for (String moduleName : splitModules) {

            int status = splitInstallSessionState.status();
            if (status == SplitInstallSessionStatus.DOWNLOADING) {
                Toast.makeText(getApplicationContext(), "Downloading " + moduleName, Toast.LENGTH_LONG).show();
            } else if (status == SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION) {
                try {
                    Toast.makeText(getApplicationContext(), "REQUIRES_USER_CONFIRMATION " + moduleName, Toast.LENGTH_LONG).show();
                    startIntentSender(splitInstallSessionState.resolutionIntent().getIntentSender(), null,
                            0, 0, 0);
                } catch (IntentSender.SendIntentException e) {
                    e.printStackTrace();
                }
            } else if (status == SplitInstallSessionStatus.INSTALLED) {

                    onSuccessfulLoad(moduleName, EPaperLauncherclassName, true);


                Toast.makeText(getApplicationContext(), "INSTALLED " + moduleName, Toast.LENGTH_LONG).show();
            } else if (status == SplitInstallSessionStatus.INSTALLING) {
                Toast.makeText(getApplicationContext(), "INSTALLING " + moduleName, Toast.LENGTH_LONG).show();
            } else if (status == SplitInstallSessionStatus.FAILED) {
                Toast.makeText(getApplicationContext(), "FAILED " + moduleName, Toast.LENGTH_LONG).show();
                Log.e(this.getClass().getName(), "Error: " + splitInstallSessionState.errorCode() + "for module " + moduleName);
            }
        }
    }
};

/**
 * Request uninstall of all features.
 */
private void requestUninstall(final String moduleName) {

    Toast.makeText(getApplicationContext(), "Requesting uninstall of all modules." +
            "This will happen at some point in the future.", Toast.LENGTH_LONG).show();

    final Set<String> installedModules = installManager.getInstalledModules();
    installManager.deferredUninstall(new ArrayList<String>(installedModules)).addOnSuccessListener(new OnSuccessListener<Void>() {
        @Override
        public void onSuccess(Void aVoid) {
            Toast.makeText(getApplicationContext(), "Uninstalling " + moduleName, Toast.LENGTH_LONG).show();
        }
    });
}

/**
 * Define what to do once a feature module is loaded successfully.
 *
 * @param moduleName The name of the successfully loaded module.
 * @param launch     `true` if the feature module should be launched, else `false`.
 */
private void onSuccessfulLoad(String moduleName, String launcherclassName, boolean launch) {
    if (launch) {
        Toast.makeText(getApplicationContext(), "onSuccessfulLoad " + moduleName,
                Toast.LENGTH_LONG).show();
            launchActivity(launcherclassName);

    }

}

/**
 * Launch an activity by its class name.
 */
private void launchActivity(String className) {

    try {


        Intent intent = new Intent();
        intent.setClassName(this.getPackageName(), className);
        startActivity(intent);


    } catch (
            Exception e)

    {
        Toast.makeText(getApplicationContext(), e.getMessage() + " ", Toast.LENGTH_SHORT).show();
        e.printStackTrace();
    }

}


@Override
protected void onDestroy() {
    installManager.unregisterListener(splitInstallStateUpdatedListener);
    super.onDestroy();
}

@Override
public void onClick(View view) {
    if (view.getId() == R.id.btn_epaper) {
        loadAndLaunchModule(EpaperModuleName, EPaperLauncherclassName);
    }
}

Ответы [ 3 ]

0 голосов
/ 19 сентября 2018

Вы можете посмотреть, как реализованы динамические функции в этом примере .

Пример кода для открытия некоторых ресурсов, расположенных в динамическом модуле, из базового модуля .

Кроме того, примеры включают в себя другие динамические модули с действиями, реализованными на Java / Kotlin и нативных.

Имейте в виду, что Playcore v1.3.4 включает исправление аналогичной ошибки. Обязательно используйте v1.3.4 или новее. Другое требование - переопределить attachBaseClassContext в действиях, которые вы выполняете в динамических модулях:

override fun attachBaseContext(newBase: Context?) {
    super.attachBaseContext(newBase)
    SplitCompat.install(this)
}

Это показано в примере с этим абстрактным классом.

0 голосов
/ 04 июля 2019

Я могу подтвердить, что решение, предоставленное @ pfmaggi , является правильным.

Это работает, когда вы передаете контекст приложения, поэтому вы должны сделать что-то вроде:

class MyApplication: SplitCompatApplication() {
...
    override fun attachBaseContext(newBase: Context?) {
        super.attachBaseContext(newBase)
        SplitCompat.install(this)
    }
...
}

и затем добавьте имя приложения в Manifest вашего базового модуля (Примечание: добавьте имя приложения в файл манифеста в вашем модуле с именем 'app' или в модуле с apply plugin: 'com.android.application' в его файле build.gradle)

0 голосов
/ 28 августа 2018

Если в динамической функции определено действие, вам нужно вызвать SplitCompat.install(this) в методе attachBaseContext, чтобы убедиться, что все новые ресурсы доступны для вашего приложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...