先抛砖引玉一下,接个例子说明,现在的例子是要实现:
一个安装的apk里面的一个activity A要去调用一个放在sd卡上的没安装的apk里面的activity B,点返回键又回到Activity A,而不是直接退出。
ok,我这里已经有现成的方法了,先上代码:
主动去加载的SD上类的activity
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
import dalvik.system.DexClassLoader;
public class MainActivity
extends Activity {
private static final String TAG = "MainActivity";
private boolean isJumped = false;
private Class localClass;
private Object instance;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
isJumped = true;
Bundle paramBundle = new Bundle();
paramBundle.putBoolean("KEY_START_FROM_OTHER_ACTIVITY", true);
String dexpath = "/mnt/sdcard/ToolA.apk";
String dexoutputpath = "/mnt/sdcard/";
LoadAPK(paramBundle, dexpath, dexoutputpath);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (isJumped) {
Bundle paramBundle = new Bundle();
paramBundle.putBoolean("KEY_START_FROM_OTHER_ACTIVITY", true);
closeAPK(paramBundle);
isJumped = false;
return true;
}
}
return super.onKeyDown(keyCode, event);
}
public void LoadAPK(Bundle paramBundle, String dexpath, String dexoutputpath) {
ClassLoader localClassLoader = ClassLoader.getSystemClassLoader();
DexClassLoader localDexClassLoader =
new DexClassLoader(dexpath, dexoutputpath, null, localClassLoader);
try {
PackageInfo plocalObject = getPackageManager().getPackageArchiveInfo(dexpath, 1);
if ((plocalObject.activities != null) && (plocalObject.activities.length > 0)) {
String activityname = plocalObject.activities[0].name;
Log.d(TAG, "activityname = " + activityname);
localClass = localDexClassLoader.loadClass(activityname);
Constructor localConstructor = localClass.getConstructor(new Class[] {});
instance = localConstructor.newInstance(new Object[] {});
Log.d(TAG, "instance = " + instance);
Method localMethodSetActivity =
localClass.getDeclaredMethod("setActivity", new Class[] {Activity.class});
localMethodSetActivity.setAccessible(true);
localMethodSetActivity.invoke(instance, new Object[] {this});
Method methodonCreate = localClass.getDeclaredMethod("onCreate", new Class[] {Bundle.class});
methodonCreate.setAccessible(true);
methodonCreate.invoke(instance, new Object[] {paramBundle});
}
return;
}
catch (Exception ex) {
ex.printStackTrace();
}
}
public void closeAPK(Bundle paramBundle) {
try {
Method methodonCreate = localClass.getDeclaredMethod("onGoBack");
methodonCreate.setAccessible(true);
methodonCreate.invoke(instance);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
另外一个是sd卡上待加载的activity:
package mobi.thinkchange.android.toola;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.Toast;
public class ToolAActivity
extends Activity {
private static final String TAG = "ToolAActivity";
private Activity otherActivity;
@Override
public void onCreate(Bundle savedInstanceState) {
boolean b = false;
if (savedInstanceState != null) {
b = savedInstanceState.getBoolean("KEY_START_FROM_OTHER_ACTIVITY", false);
if (b) {
this.otherActivity.setContentView(new TBSurfaceView(this.otherActivity));
}
}
if (!b) {
super.onCreate(savedInstanceState);
setContentView(new TBSurfaceView(this));
}
}
public void setActivity(Activity paramActivity) {
Log.d(TAG, "setActivity..." + paramActivity);
this.otherActivity = paramActivity;
}
public void onGoBack() {
otherActivity.setContentView(R.layout.main);
}
}
上面是实现我说的例子最核心的两个类,全部代码详见:http://download.csdn.net/detail/androidzhaoxiaogang/4903804
(代码只是片段,如果要实际应用还需要完善,比如在返回的时候终端执行的runnable可参考我的另外一篇文章如何终端执行的java线程)
也许网上有很多关于QQ游戏大厅的分析或者类似上面的例子,但是我想做进一步的分析。
1.我们知道一个activity具有严格意义上的生命周期必须要在ActivityThread里面去创建,所以通过DexClassLoader加载的ActivityB是没有生命周期的,它也就是一个普通的类;
2.有人会问,为什么还要让ActivityA 来加载ActivityB,而不是直接ActivityA去load 另外一个类比如classC呢? 这个问题很简单,因为我们在打包成APK的时候,有activity会更方便和直观(自己去体会)。简单的游戏,往往一个activity就够了。那么ActivityA 也仅仅只需要加载一个类实例。
分享到:
相关推荐
像qq游戏那样,从大厅登陆,认证后登陆到游戏服务器。进行各项游戏。
仿QQ游戏大厅原理demo
易语言解除QQ游戏大厅多开限制源码
易语言解除QQ游戏大厅多开限制源码,解除QQ游戏大厅多开限制,创建进程,我要解除大厅多开限制,大厅进程检测
仿照QQ游戏大厅写的一个大厅,觉得不错,希望大家一起学习!
勇芳QQ游戏大厅多开补丁功能:让1台电脑能够同时打开多个QQ游戏,支持QQ游戏2015系列及2014系列各版本。世界上支持最多QQ游戏大厅的多开补丁软件,更新速度非常快。可以删除关闭大厅后的小广告,进入大厅即刻享受...
基于MFC开发的QQ游戏大厅客户端界面 ,实现了游戏大厅的基本功能
java编写的QQ游戏大厅,java疯狂实战系列
这个是wm6.1上的qq 游戏大厅for sp自动屏幕分辨率 在我的585上完美运行,你的手机装上它,从此不用在电脑前就可与你的QQ好友一起PLAY GAME!喜欢完QQ上斗地主的朋友一定要下哦
思量QQ游戏大厅多开器简介 1. QQ游戏大厅多开多房间辅助,使一台电脑不受限制地开任意多个游戏大厅,登陆多个QQ号进行游戏,刷分、升级必备; 2. 支持所有简体版QQ游戏大厅多开,支持多房间。 注意:本...
NULL 博文链接:https://kaka100.iteye.com/blog/846670
一个C/S架构的仿QQ游戏的五子棋游戏大厅项目,能实现多人连线对战 主要用到的技术是Java的Scoket、多线程、Swing
易语言源码易语言解除QQ游戏大厅多开限制源码.rar 易语言源码易语言解除QQ游戏大厅多开限制源码.rar 易语言源码易语言解除QQ游戏大厅多开限制源码.rar 易语言源码易语言解除QQ游戏大厅多开限制源码.rar 易语言...
vc实现仿QQ、联众游戏大厅,如果说不好的话,我不会要这么高分,如果骗了大家,欢迎举报~
五子棋网络游戏大厅版,VB模仿QQ游戏源代码,烈火下载强烈推荐您下载,以前介绍过Delphi开发的单机版五子棋源码和网页Flash五子棋网络对战版,今天特别推荐仿QQ游戏的界面的网络版,包含服务端和客户端,可边玩游戏...
VC仿QQ游戏大厅的树型展开菜单控件dddddddddddddddddddddddddddddddddd
QQ游戏连连看源码,直接就可以编译,秒杀一切QQ游戏连连看
仿QQ游戏大厅,很棒!