天天看点

android 反射执行apk,Android反射调用未安装的APK打开activity

1.思路:

1.1 通过getPackageArchiveInfo方法获取sd卡的未安装的APK信息和Activity

1.2 获取到插件Activity的信息之后,通过反射得到插件Activity的实例

1.3 获取到插件Activity的实例后通过构造函数将宿主的上下文传递到插件APP

1.4 在反射调用插件activity的onCreate方法

2.宿主代码

package com.lazy.dex;

import android.annotation.SuppressLint;

import android.app.Activity;

import android.content.pm.PackageInfo;

import android.os.Bundle;

import android.os.Environment;

import android.support.v7.app.AppCompatActivity;

import android.util.Log;

import android.view.View;

import android.view.View.OnClickListener;

import dalvik.system.DexClassLoader;

import java.io.File;

import java.lang.reflect.Constructor;

import java.lang.reflect.Method;

public class MainActivity extends AppCompatActivity {

private String mClass;

String dexPath = Environment.getExternalStorageDirectory().toString() + File.separator + "a";

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

findViewById(R.id.bt).setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

launchTargetActivity();

}

});

}

@SuppressLint("NewApi")

protected void launchTargetActivity() {

//根据sd卡的路径获取未安装的apk的信息

PackageInfo packageInfo = getPackageManager().getPackageArchiveInfo(dexPath, 1);

if ((packageInfo.activities != null)

&& (packageInfo.activities.length > 0)) {

String activityName = packageInfo.activities[0].name;//获取插件中第一个activity

mClass = activityName;

launchTargetActivity(mClass);

}

}

@SuppressLint("NewApi")

protected void launchTargetActivity(final String className) {

Log.e("MainActivity", "start launchTargetActivity, className=" + className);

File dexOutputDir = this.getDir("dex", 0);

final String dexOutputPath = dexOutputDir.getAbsolutePath();

ClassLoader localClassLoader = ClassLoader.getSystemClassLoader();

DexClassLoader dexClassLoader = new DexClassLoader(dexPath,

dexOutputPath, null, localClassLoader);

try {

Class> localClass = dexClassLoader.loadClass(className);//创建插件Activity的实例

//调用插件Activity的构造函数,将当前activity的上下文传递到插件activity中去

Constructor> localConstructor = localClass.getConstructor(new Class[]{Activity.class});

Object instance = localConstructor.newInstance(new Object[]{this});

Log.e("MainActivity", "instance = " + instance);

Method onCreate = localClass.getDeclaredMethod("onCreate", new Class[]{Bundle.class});

onCreate.setAccessible(true);

Bundle bundle = new Bundle();

onCreate.invoke(instance, bundle);//调用插件activity的onCreate方法

} catch (Exception e) {

Log.e("MainActivity", e.getMessage());

}

}

}

3.APP插件代码

package com.Company.Demo;

import android.app.Activity;

import android.os.Bundle;

import android.util.Log;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.LinearLayout;

import android.widget.Toast;

public class TestActivity extends Activity implements OnClickListener {

private Activity otherActivity;

public TestActivity() {

super();

}

public TestActivity(Activity context) {

super();

otherActivity = context;

Log.e("TestActivity", otherActivity.toString() );

}

@Override

public void onCreate(Bundle savedInstanceState) {

if (otherActivity != null) {

// 使用TestHallActivity的上下文引用创建View并添加到根视图

Button button = new Button(otherActivity);

button.setText("我是插件TestActivity");

button.setOnClickListener(this);

LinearLayout root = new LinearLayout(otherActivity);

root.addView(button);

//使用宿主的上线文就不能使用插件的资源了

otherActivity.setContentView(root);

} else {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

}

}

private String getRoomMessage() {

return "我是插件TestActivity";

}

@Override

public void onClick(View v) {

if (otherActivity != null) {

// Toast.makeText(this, "This is Room A!", Toast.LENGTH_SHORT).show();是不合适的调用

Toast.makeText(otherActivity, "我是插件TestActivity", Toast.LENGTH_SHORT).show();

} else {

Toast.makeText(this, "我是插件TestActivity", Toast.LENGTH_SHORT).show();

}

}

}