如何启动Manifest中提到的不存在的Activity?

时间:2017-11-20 10:37:20

标签: android

我正在尝试开发一个" Dynamic" 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]]

我是否可以采用一种方法在运行时成功实例化Android Activity?

有没有办法可以添加"临时"或者" shell"活动到我的申请路径?然后替换"临时"我的动态实例的活动?

更新

My Manifest XML包含此条目

<activity
  android:name=".Dynamic"
  android:label="@string/title_activity_dynamic"
  android:theme="@style/AppTheme.NoActionBar" />

然而,没有名为&#34; Dynamic&#34;包含在我的申请中。

我正在使用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);

2 个答案:

答案 0 :(得分:12)

CAN 启动此类Activity(假设您有 虚拟 清单{ {1}}条目。)如果您不喜欢这种技巧,请使用 Activity (他们不需要清单中的条目)。<或者使用WebViewJavaScript,例如Apache Cordova et-al(跨平台!)。
ByteBuddy(作为Byte Buddy的作者@Rafael Winterhalter的赞誉)看起来很酷,也许是一个学习曲线。为什么不下载linked project并尝试这两种技术 以下是Android Studio Fragments项目includeByteBuddy Gradle的方式:

build.gradle
  

我怎样才能找到&#34;我在运行时动态实例化类?

DEX文件的外部加载(类字节代码)

See my answer here并按照源代码和教程(Apache Ant {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' } } 兼容,Eclipse}和Android Studio build.xml示例Gradle的链接进行操作相同的代码,您需要一些这些项目提供的自定义构建步骤 代码段:

build.gradle
  

问:如何添加活动,我无法将其添加到清单?
答:使用   片段,他们不需要清单中的条目。

答案 1 :(得分:5)

我已设法调用动态实例化的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);

方法委派类

public class TargetActivity {

    public static void intercept(Bundle savedInstanceState, @This AppCompatActivity thiz) {
        thiz.setContentView(R.layout.activity_fourth);
    }
}

即使这会产生预期的结果,但在我调用super.onCreate(savedInstanceState)(我认为)之后调用setContent时仍会出现问题。

使用优秀的ByteBuddy库是一种比使用DEX操作更好的方法。