Android 未找到加载的动态功能的主活动类

Android 未找到加载的动态功能的主活动类,android,android-intent,android-activity,module,bundle,Android,Android Intent,Android Activity,Module,Bundle,我正在尝试向我的应用程序添加动态功能支持,因此我创建了一个测试应用程序 测试应用程序有一个主应用程序部分,用于加载动态功能并尝试执行它 功能模块已将MainActivity称为main activity 我得到的是,功能加载过程之所以有效,是因为我获得了成功的日志消息,并获得了已安装模块的列表 请注意,该应用程序是在虚拟设备上运行的,没有真正的下载,我认为一切都是通过AndroidStudio的部署过程自动安装的 事实上,我在尝试调用模块的主要活动时遇到了这种错误: W/System.err:

我正在尝试向我的应用程序添加动态功能支持,因此我创建了一个测试应用程序

测试应用程序有一个主应用程序部分,用于加载动态功能并尝试执行它

功能模块已将MainActivity称为main activity

我得到的是,功能加载过程之所以有效,是因为我获得了成功的日志消息,并获得了已安装模块的列表

请注意,该应用程序是在虚拟设备上运行的,没有真正的下载,我认为一切都是通过AndroidStudio的部署过程自动安装的

事实上,我在尝试调用模块的主要活动时遇到了这种错误:

W/System.err: android.content.ActivityNotFoundException: Unable to find explicit activity class {com.example.dynamicfeature1/MainActivityCalled}; have you declared this activity in your AndroidManifest.xml?
W/System.err:     at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1805)
    at android.app.Instrumentation.execStartActivity(Instrumentation.java:1523)
    at android.app.Activity.startActivityForResult(Activity.java:4225)
    at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:767)
    at android.app.Activity.startActivityForResult(Activity.java:4183)
    at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:754)
    at android.app.Activity.startActivity(Activity.java:4522)
    at android.app.Activity.startActivity(Activity.java:4490)
    at com.example.mymodules.MainActivity$2.onClick(MainActivity.java:227)
    at android.view.View.performClick(View.java:5637)
    at android.view.View$PerformClick.run(View.java:22429)
    at android.os.Handler.handleCallback(Handler.java:751)
    at android.os.Handler.dispatchMessage(Handler.java:95)
所有操作都按照 除了对模块活动的显式调用之外,我猜必须有目的地执行该活动(在上面链接的页面中没有示例)

下面是代码的重要部分:

new OnSuccessListener<Integer>() {
                        @Override
                        public void onSuccess(Integer result) {
                            Log.d("request feature load","success "+result);
                            mySessionId=result;
                            Set<String> installedModules = splitInstallManager.getInstalledModules();
                            String[] modules = new String[installedModules.size()];

                            installedModules.toArray(modules);
                            for (int i=0;i<modules.length;i++)
                            {
                                Log.d("module",modules[i]);
                            }


                        }
                    })
所有的主要活动都有这种被忽略的方法

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    // Emulates installation of on demand modules using SplitCompat.
    SplitCompat.installActivity(this);
    Log.d("attachBaseContext",base.getPackageName().toString());
}
安装时动态功能模块中未调用的

我的代码有什么问题

这是应用程序的主要活动

package com.example.mymodules;

...imports...

public class MainActivity extends AppCompatActivity {
private static int MY_REQUEST_CODE=1;
Activity activity;
int mySessionId;

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    // Emulates installation of future on demand modules using SplitCompat.
    SplitCompat.install(this);
 Log.d("attachBaseContext",base.getPackageName().toString());

}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == MY_REQUEST_CODE) {
        // Handle the user's decision. For example, if the user selects "Cancel",
        // you may want to disable certain functionality that depends on the module.
    }
}


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    activity = this;
    setContentView(R.layout.activity_main);
    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    Button button1 = findViewById(R.id.button1);
    button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            // Creates an instance of SplitInstallManager.
            final SplitInstallManager splitInstallManager =
                    SplitInstallManagerFactory.create(activity);

// Creates a request to install a module.
            SplitInstallRequest request =
                    SplitInstallRequest
                            .newBuilder()
                            // You can download multiple on demand modules per
                            // request by invoking the following method for each
                            // module you want to install.
                            .addModule("dynamicfeature1")

                            .build();

// Creates a listener for request status updates.
            SplitInstallStateUpdatedListener listener =new SplitInstallStateUpdatedListener() {
                @Override
                public void onStateUpdate(SplitInstallSessionState state) {
                    if (state.status() == SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION) {
                        // Displays a dialog for the user to either “Download”
                        // or “Cancel” the request.
                        try {
                            splitInstallManager.startConfirmationDialogForResult(
                                    state,
                                    /* activity = */ activity,
                                    // You use this request code to later retrieve the user's decision.
                                    /* requestCode = */ MY_REQUEST_CODE);
                        } catch (IntentSender.SendIntentException e) {
                            e.printStackTrace();
                        }
                    }

                    if (state.sessionId() == mySessionId) {
                        switch (state.status()) {

                            case SplitInstallSessionStatus.INSTALLED:
                                Context tempNewContext=null;
                                try {
                                    tempNewContext = activity.createPackageContext(activity.getPackageName(), 0);
                                } catch (PackageManager.NameNotFoundException e) {

                                }
                                final Context newContext =tempNewContext;
                                // If you use AssetManager to access your app’s raw asset files, you’ll need
                                // to generate a new AssetManager instance from the updated context.
                                AssetManager am = newContext.getAssets();


                                if (BuildCompat.isAtLeastO()) {
                                    // Updates the app’s context with the code and resources of the
                                    // installed module.
                                    SplitInstallHelper.updateAppInfo(newContext);
                                    new Handler().post(new Runnable() {
                                        @Override public void run() {
                                            // Loads contents from the module using AssetManager
                                            AssetManager am = newContext.getAssets();

                                        }
                                    });
                                } else
                                {SplitInstallHelper.updateAppInfo(newContext);}

                        }
                    }
                }

            } ;
            splitInstallManager.registerListener(listener);
            splitInstallManager
                    // Submits the request to install the module through the
                    // asynchronous startInstall() task. Your app needs to be
                    // in the foreground to submit the request.
                    .startInstall(request)
                    // You should also be able to gracefully handle
                    // request state changes and errors. To learn more, go to
                    // the section about how to Monitor the request state.
                    .addOnSuccessListener(new OnSuccessListener<Integer>() {
                        @Override
                        public void onSuccess(Integer result) {
                            Log.d("request feature load","success "+result);
                            mySessionId=result;
                            Set<String> installedModules = splitInstallManager.getInstalledModules();
                            String[] modules = new String[installedModules.size()];

                            installedModules.toArray(modules);
                            for (int i=0;i<modules.length;i++)
                            {
                                Log.d("module",modules[i]);
                            }


                        }
                    })
                    .addOnFailureListener(new OnFailureListener() {
                        void checkForActiveDownloads() {
                            splitInstallManager
                                    // Returns a SplitInstallSessionState object for each active session as a List.
                                    .getSessionStates()
                                    .addOnCompleteListener(
                                            new OnCompleteListener<List<SplitInstallSessionState>>() {
                                                @Override
                                                public void onComplete(Task<List<SplitInstallSessionState>> task) {
                                                    if (task.isSuccessful()) {
                                                        // Check for active sessions.
                                                        for (SplitInstallSessionState state : task.getResult()) {
                                                            if (state.status() == SplitInstallSessionStatus.DOWNLOADING) {
                                                                // Cancel the request, or request a deferred installation.
                                                            }
                                                        }
                                                    }
                                                }


                                            });
                        }

                        @Override
                        public void onFailure(Exception e) {
Log.d("request feature load","failure "+e.getMessage());
                            switch (((SplitInstallException) e).getErrorCode()) {
                                case SplitInstallErrorCode.NETWORK_ERROR:
                                    // Display a message that requests the user to establish a
                                    // network connection.
                                    break;
                                case SplitInstallErrorCode.ACTIVE_SESSIONS_LIMIT_EXCEEDED:
                                    checkForActiveDownloads();
                            }

                        }
                    });




        }
    });
   Button button2 = findViewById(R.id.button2);
    button2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Log.d("feature1","called");
 Intent intent=new Intent();
            intent.setClassName("com.example.dynamicfeature1","MainActivityCalled");

            try{  startActivity(intent);}
            catch (Exception e){
                e.printStackTrace();
            }

        }
    });
   Button button3 = findViewById(R.id.button3);
    button3.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Log.d("feature2","called");
        }
    });
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}



@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}
}
和模块清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:dist="http://schemas.android.com/apk/distribution"
package="com.example.dynamicfeature1">

<dist:module
    dist:instant="false"
    dist:title="@string/title_dynamicfeature1">
    <dist:delivery>
        <dist:on-demand />
    </dist:delivery>

    <dist:fusing dist:include="false" />
</dist:module>

<application>
    <activity
        android:name=".MainActivityCalled"
        android:label="@string/title_activity_main"
        android:theme="@style/AppTheme.NoActionBar"></activity>
</application>

</manifest>

调用活动的正确指令是

intent. setClassName(BuildConfig.APPLICATION_ID, "com.example.dynamicfeature.MainActivityCalled");
它工作,活动被调用

注意BuildConfig.APPLICATION\u ID是

com.example.mymodules
如果此字符串也用于动态模块中,则可以进行交叉调用:

-从一个模块到另一个模块

-从一个模块到主应用程序


但是您不希望在模块中使用BuildConfig.APPLICATION\u ID,因为它是一个不同的值,因此必须将主字符串值放入变量中。

调用活动的正确指令是

intent. setClassName(BuildConfig.APPLICATION_ID, "com.example.dynamicfeature.MainActivityCalled");
它工作,活动被调用

注意BuildConfig.APPLICATION\u ID是

com.example.mymodules
如果此字符串也用于动态模块中,则可以进行交叉调用:

-从一个模块到另一个模块

-从一个模块到主应用程序


但是您不希望在模块中使用BuildConfig.APPLICATION\u ID,因为它是一个不同的值,因此必须将主字符串值放入变量中。

谢谢。我也遇到了同样的问题,并且还必须使用父模块的应用程序id来启动子模块中的活动。因此,我用来创建intent的代码是
intent.setClassName(.BuildConfig.APPLICATION_ID,activityClass.getName())伙计,谢谢你!我已经被困在这个问题上两天了。。。使用BuildConfig.APPLICATION\u ID非常有效。谢谢。我也遇到了同样的问题,并且还必须使用父模块的应用程序id来启动子模块中的活动。因此,我用来创建intent的代码是
intent.setClassName(.BuildConfig.APPLICATION_ID,activityClass.getName())伙计,谢谢你!我已经被困在这个问题上两天了。。。使用BuildConfig.APPLICATION\u ID工作得很好。
com.example.mymodules