当通过Android Studio运行配置键入启动动态特性模块中的活动
时,我得到以下警告:活动'someActivity'未在AndroidManifest.xml
中声明。(因为它是在动态特性模块的androidmanifest.xml
中声明的)。供参考,这是正在使用的库:
// https://developer.android.com/guide/app-bundle/playcore
api "com.google.android.play:core:1.6.4"
运行配置显示并部署了这两个模块,但它只识别来自基础模块AndroidManifest.xml
的活动。如何在动态特性模块中启动活动?
边注:尝试安装已部署的功能模块时,似乎不会安装:
I/PlayCore: SplitInstallListenerRegistry : registerListener
I/PlayCore: SplitInstallInfoProvider : No metadata found in AndroidManifest.
I/PlayCore: SplitInstallService : startInstall([feature_module],[])
I/PlayCore: SplitInstallService : Initiate binding to the service.
I/PlayCore: SplitInstallService : ServiceConnectionImpl.onServiceConnected(ComponentInfo{com.android.vending/com.google.android.finsky.splitinstallservice.SplitInstallService})
I/PlayCore: SplitInstallService : linkToDeath
I/PlayCore: SplitInstallService : onError(-5)
I/PlayCore: SplitInstallService : Unbind from service.
其中-5
表示splitinstallerrorcode.api_not_available
(可能是因为它是调试构建);尽管如此,getInstalledModules()
应该找到部署的功能模块...但它没有找到。SplitInstallInfoProvider:在AndroidManifest中找不到元数据
似乎是这个问题--当删除“默认apk”而不是“apk from app bundle”时,将安装功能模块。
由于不能在基本模块的AndroidManifest.xml
中引用特性模块活动,所以我编写了一个SplitInstallActivity
,它驻留在基本模块的Debug
源代码集中,在那里它也可用于测试。可以使用run-configuration调用它,该配置传递启动标志:
-e "moduleName" "feature_module" -e "className" "com.acme.feature.SomeActivity"
它或者通过modulename
安装功能模块,或者通过classname
启动活动
。
这至少在部署“默认APK”而不是“app bundle中的APK”时起作用。
argumentkeys.java
public class ArgumentKeys {
/** {@link SplitInstallActivity} dynamic features, the module name */
public static final String ARGUMENT_FEATURE_MODULE_MODULE_NAME = "moduleName";
/** {@link SplitInstallActivity} dynamic features, the activity class name to launch */
public static final String ARGUMENT_FEATURE_MODULE_CLASS_NAME = "className";
}
SplitInstallActivity.java
/**
* Split-Install {@link AppCompatActivity}.
* @author Martin Zeitler
**/
public class SplitInstallActivity extends AppCompatActivity implements SplitInstallStateUpdatedListener {
private static final String LOG_TAG = SplitInstallActivity.class.getSimpleName();
private SplitInstallRequest request;
private SplitInstallManager sim;
private String moduleName;
private String className;
public SplitInstallActivity() {}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* instance the {@link SplitInstallManager}: */
this.sim = SplitInstallManagerFactory.create(this.getApplicationContext());
/* obtain the feature module & class name from arguments */
if(this.getIntent() != null) {
Bundle extras = this.getIntent().getExtras();
if(extras != null) {
this.moduleName = extras.getString(ArgumentKeys.ARGUMENT_FEATURE_MODULE_MODULE_NAME);
this.className = extras.getString(ArgumentKeys.ARGUMENT_FEATURE_MODULE_CLASS_NAME);
if(this.moduleName != null && this.className != null) {
this.startFeatureActivity(this.moduleName, this.className);
} else {
Log.e(LOG_TAG, "module and class are required.");
}
}
}
}
/** it listens for the split-install session state */
@Override
public void onStateUpdate(SplitInstallSessionState state) {
if(state.errorCode() == SplitInstallErrorCode.NO_ERROR && state.status() == SplitInstallSessionStatus.INSTALLED) {
Log.d(LOG_TAG, "dynamic feature " + this.moduleName + " had been installed.");
this.startFeatureActivity(this.moduleName, this.className);
} else {
// this.OnSplitInstallStatus(state);
}
}
/** it checks if the dynamic feature module is installed and then either installs it - or starts the desired activity */
private void startFeatureActivity(@NonNull String moduleName, @NonNull String className) {
if (this.sim.getInstalledModules().contains(moduleName)) {
Log.d(LOG_TAG, "dynamic feature module " + moduleName + " already installed.");
Intent intent = this.getIntent();
intent.setClassName(BuildConfig.APPLICATION_ID, className);
this.startActivity(intent);
this.finish();
} else {
Log.d(LOG_TAG, "dynamic feature module " + moduleName + " is not installed.");
this.installFeatureModule(moduleName);
}
}
/** it installs a dynamic feature module on demand */
private void installFeatureModule(@NonNull String moduleName) {
Log.d(LOG_TAG, "dynamic feature module " + moduleName + " will be installed.");
this.request = SplitInstallRequest.newBuilder().addModule(moduleName).build();
this.sim.registerListener(this);
this.sim.startInstall(this.request);
}
...
}
使用ActivityTestRule<?>
可以自动启动特定的活动
:
@Rule
public ActivityTestRule<SplitInstallActivity> mRule = new ActivityTestRule<SplitInstallActivity>(SplitInstallActivity.class) {
@Override
protected Intent getActivityIntent() {
Intent intent = new Intent();
Bundle extras = new Bundle();
extras.putString(ArgumentKeys.ARGUMENT_FEATURE_MODULE_MODULE_NAME, "feature_module");
extras.putString(ArgumentKeys.ARGUMENT_FEATURE_MODULE_CLASS_NAME, "com.acme.feature.SomeActivity");
intent.putExtras(extras);
return intent;
}
};
androidTestDebugImplementation "com.google.android.gms:play-services-basement:17.1.1"
androidTestDebugImplementation "com.google.android.play:core:1.6.4"
> Task :feature_module:processDebugAndroidTestResources FAILED
AGPBI: {"kind":"error","text":"Android resource linking failed","sources":[{"file":"/home/user/.gradle/caches/transforms-2/files-2.1/7435b27a13269cffdd35a7dd69f0b9d2/core-1.6.4/AndroidManifest.xml","position":{"startLine":8,"startColumn":4,"endColumn":277}}],"original":"/home/user/.gradle/caches/transforms-2/files-2.1/7435b27a13269cffdd35a7dd69f0b9d2/core-1.6.4/AndroidManifest.xml:9:5-278: AAPT: error: resource style/Theme.PlayCore.Transparent (aka com.acme.feature.test:style/Theme.PlayCore.Transparent) not found.","tool":"AAPT"}
AGPBI: {"kind":"error","text":"Android resource linking failed","sources":[{"file":"/home/user/.gradle/caches/transforms-2/files-2.1/c1b8b45e2f49fbe83ea45d80000bd6e9/jetified-play-services-basement-17.0.0/AndroidManifest.xml","position":{"startLine":22,"startColumn":8,"endLine":24,"endColumn":68}}],"original":"/home/user/.gradle/caches/transforms-2/files-2.1/c1b8b45e2f49fbe83ea45d80000bd6e9/jetified-play-services-basement-17.0.0/AndroidManifest.xml:23:9-25:69: AAPT: error: resource integer/google_play_services_version (aka com.acme.feature.test:integer/google_play_services_version) not found.","tool":"AAPT"}
我正在尝试实现动态交付类型的APP。首先,我在create模块之后创建新项目,用于此动态步骤 我的crate类和想要访问资源文件夹的使用布局,可绘制文件夹。 在主模块级实现 实现'com.google.android.play:core:1.2.0'和dynamicFeatures=[“:Dynamic_Feature”] 错误:找不到符号变量activity_main 错误:找不到符号变量iv_
在传统桌面操作系统中,用户空间和内核空间是分开的,应用程序运行在用户空间,内核以及内核模块则运行于内核空间,其中内核模块可以动态加载与删除以扩展内核功能。dlmodule 则是 RT-Thread 下,在内核空间对外提供的动态模块加载机制的软件组件。在 RT-Thread v3.1.0 以前的版本中,这也称之为应用模块(Application Module),在 RT-Thread v3.1.0
动态模块接口 结构体 struct rt_dlmodule 动态模块控制块 更多... 类型定义 typedef void(* rt_dlmodule_init_func_t) (struct rt_dlmodule *module) 动态模块初始化函数指针类型定义 typedef void(* rt_dlmodule_cleanup_func_t) (struct rt_
我正在构建一个android应用程序,我需要从后台开始一项活动。我正在使用ForegroundStarter来扩展服务,以实现这一点。我有一个活动屏幕。我需要从前台服务运行的类。活动的广告屏幕。除了Android10,其他所有Android版本的课程都可以正常运行(从后台开始)。 前场先发。班 我读到在Android10上从后台启动活动有一些限制。这个代码似乎不再有效了。https://devel
我正在开发一个运行在PC上的Java测试控制器应用程序。它有: 在android手机上安装应用程序: 怎么做有什么想法吗?
我想这是一个标准的知识问题,但是是否会以线程形式运行? 我想要的是与生产者/消费者的并发会话,这些会话编写/监听他们的特定队列。我已经尝试通过将连接传递给线程来编写一个自定义线程,但是当我创建生产者时,我遇到了一个错误,“我不能在未注册的会话上启动生产者”。