我正在尝试开发一个"动态"Android应用程序.
动态,我在清单中列出了一个在运行时"构建"的活动.
我可以很好地构建所需的活动,但是,当我尝试启动它时,我的应用程序失败了......
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.research.ps/com.research.Dynamic}: java.lang.ClassNotFoundException:
Didn't find class "com.research.Dynamic" on path: DexPathList[[zip file "/data/app/com.research.ps-1/base.apk"],nativeLibraryDirectories=[/data/app/com.research.ps-1/lib/arm,
/data/app/com.research.ps-1/base.apk!/lib/armeabi-v7a, /vendor/lib, /system/lib]]
Run Code Online (Sandbox Code Playgroud)
有没有一种方法可以在运行时成功实例化Android Activity?
有没有办法在我的应用程序路径中添加"临时"或"shell"活动?然后用我的动态实例替换"临时"活动?
UPDATE
My Manifest XML包含此条目
<activity
android:name=".Dynamic"
android:label="@string/title_activity_dynamic"
android:theme="@style/AppTheme.NoActionBar" />
Run Code Online (Sandbox Code Playgroud)
但是,我的应用程序中没有包含名为"Dynamic"的Activity.
我正在使用ByteBuddy构建我的动态活动: -
final Class<? extends android.support.v7.app.AppCompatActivity> dynamicType = new ByteBuddy(ClassFileVersion.JAVA_V8)
.subclass(android.support.v7.app.AppCompatActivity.class, IMITATE_SUPER_CLASS)
.name("com.research.Dynamic")
.make()
.load(getClass().getClassLoader(), new AndroidClassLoadingStrategy.Wrapping(this.getDir("dexgen", Context.MODE_PRIVATE)))
.getLoaded();
final Intent intent = new Intent(this, dynamicType);
startActivity(intent);
Run Code Online (Sandbox Code Playgroud)
Jon*_*win 12
是的,你CAN开始这样的Activity(假设你有一个虚拟清单 Activity条目).
如果您不喜欢这种技术,请使用Fragments(它们不需要清单中的条目).
或者使用像Apache Cordova等人的WebView和JavaScript(跨平台!).ByteBuddy(也是Byte Buddy的@Rafael Winterhalter的作者)看起来很酷,也许是一个学习曲线.为什么不下载链接的项目并尝试这两种技术.
以下是Android Studio 项目()中的方法:
include ByteBuddyGradlebuild.gradle
android {
compileSdkVersion 25
buildToolsVersion '25'
dependencies {
compile 'com.android.support:appcompat-v7:25'
compile 'net.bytebuddy:byte-buddy:1.7.9'
compile 'net.bytebuddy:byte-buddy-android:1.7.9'
}
}
Run Code Online (Sandbox Code Playgroud)
我如何在运行时"找到"我的动态实例化类?
在这里查看我的答案并按照源代码和教程的链接(Apache Ant { Eclipsecompatible,build.xml}和Android Studio 相同代码的Gradle示例build.gradle,您需要一些这些项目提供的自定义构建步骤).
代码段:
// Internal storage where the DexClassLoader writes the optimized dex file to.
final File optimizedDexOutputPath = getDir(SECONDARY_DEX_INTERNAL_DIR, Context.MODE_PRIVATE);
// Initialize the class loader with the secondary dex file.
DexClassLoader cl = new DexClassLoader(dexInternalStoragePath.getAbsolutePath(),
optimizedDexOutputPath.getAbsolutePath(),
null,
getClassLoader());
Class libProviderClazz = null;//variable libProviderClazz of type Class
try {
// Load the library class from the class loader.
libProviderClazz = cl.loadClass(PROVIDER_CLASS);
// Cast the return object to the library interface so that the
// caller can directly invoke methods in the interface.
// Alternatively, the caller can invoke methods through reflection,
// which is more verbose and slow.
LibraryInterface lib = (LibraryInterface) libProviderClazz.newInstance();
}
catch (Exception exception)
{
// Handle exception gracefully here.
exception.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)
问:如何添加活动,我无法将其添加到清单中?
答:使用片段,它们不需要清单中的条目.
我已设法调用动态实例化的Activity并使用ByteBuddy设置所需的布局内容.
这是如何做
final DynamicType.Unloaded<? extends AppCompatActivity> dynamicType = new ByteBuddy(ClassFileVersion.JAVA_V8)
.subclass(AppCompatActivity.class)
.name(CLASS_NAME)
.method(named("onCreate").and(takesArguments(1)))
.intercept(MethodDelegation.to(TargetActivity.class).andThen(SuperMethodCall.INSTANCE))
.make();
final Class<? extends AppCompatActivity> dynamicTypeClass = dynamicType.load(getClassLoader(), new AndroidClassLoadingStrategy.Injecting(this.getDir("dexgen", Context.MODE_PRIVATE))).getLoaded();
final Intent intent = new Intent(this, dynamicTypeClass);
startActivity(intent);
Run Code Online (Sandbox Code Playgroud)
方法委托类
public class TargetActivity {
public static void intercept(Bundle savedInstanceState, @This AppCompatActivity thiz) {
thiz.setContentView(R.layout.activity_fourth);
}
}
Run Code Online (Sandbox Code Playgroud)
即使这给出了期望的结果,它仍然存在问题,因为super.onCreate(savedInstanceState)在我打电话之后进行了呼叫setContent(我认为).
使用优秀的ByteBuddy库是一种比使用DEX操作更好的方法.
| 归档时间: |
|
| 查看次数: |
567 次 |
| 最近记录: |