Android外掛技術——(三)載入未安裝apk
上一篇我們介紹了載入已安裝apk,本篇將介紹載入未安裝apk。
未安裝apk由於系統毫不知情,因此無法通過系統api獲取其上下文,自然也就無法獲取其資源。接下來,我們將另闢蹊徑來解決這個問題。
步驟如下:
一、採用上一篇中的Android Host工程,仍然匯出外掛介面類
二、新建Android外掛工程,匯入外掛介面類,編譯成apk,並push到手機
三、執行Android Host,載入外掛
Android Host工程如下
public class MainActivity extends Activity {
private Button mBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBtn = (Button) findViewById(R.id.btn);
mBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
loadPlugin();
}
});
}
private void loadPlugin() {
File jarFile = new File(getExternalCacheDir(), "AndroidPlugin.apk");
File outputDir = getDir("plugin", 0);
FileUtils.deleteDirectory(outputDir);
DexClassLoader loader = new DexClassLoader(jarFile.getAbsolutePath(),
outputDir.getAbsolutePath(), null, getClass().getClassLoader());
try {
Class<?> clazz = loader.loadClass("com.example.androidplugin.MainActivity");
IPlugin plugin = (IPlugin) clazz.newInstance();
String text = String.format("getInt: %d, getString: %s", plugin.getInt(),
plugin.getString());
Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Android外掛工程
public class MainActivity extends Activity implements IPlugin {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public int getInt() {
// TODO Auto-generated method stub
return 100;
}
@Override
public String getString() {
// TODO Auto-generated method stub
return "Hello, This is Plugin!";
}
}
有一點需要注意:外掛工程中不能直接匯入外掛介面jar,如下
不能選擇Add JARs,而是應該選擇Add External JARs,否則會報執行時錯誤如下
我們注意到外掛工程中外掛的介面jar放在libs_ex目錄中,而不是libs目錄中,就是為避免eclipse自動將libs中的jar直接新增到工程中了。
執行Host工程,可以成功地載入外掛apk中的MainActivity,並呼叫其外掛介面getString返回了字串,然而這裡MainActivity只是被當做了一個普通java類被調起而已,並不是真正意義上的Android元件,我們可以嘗試著在getString時返回Android字串資源。如下:
public class MainActivity extends Activity implements IPlugin {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public int getInt() {
// TODO Auto-generated method stub
return 100;
}
@Override
public String getString() {
// TODO Auto-generated method stub
return getString(R.string.hello_world);
}
}
執行Host調起外掛,結果會崩潰,日誌如下:
可見外掛中的Activity只是一個普通的Java類,無法獲取其系統資源,要獲取系統資源必須獲取外掛的Resources,Host中修改如下:
public class MainActivity extends Activity {
private Button mBtn;
private Resources mPluginResources;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBtn = (Button) findViewById(R.id.btn);
mBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
loadPlugin();
}
});
}
private void loadPlugin() {
File jarFile = new File(getExternalCacheDir(), "AndroidPlugin.apk");
File outputDir = getDir("plugin", 0);
FileUtils.deleteDirectory(outputDir);
DexClassLoader loader = new DexClassLoader(jarFile.getAbsolutePath(),
outputDir.getAbsolutePath(), null, getClass().getClassLoader());
try {
Class<?> clazz = loader.loadClass("com.example.androidplugin.MainActivity");
IPlugin plugin = (IPlugin) clazz.newInstance();
loadResources(jarFile.getAbsolutePath());
int resId = mPluginResources.getIdentifier("hello_world", "string",
"com.example.androidplugin");
String text = mPluginResources.getString(resId);
Toast.makeText(this, plugin.getInt() + text, Toast.LENGTH_SHORT).show();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void loadResources(String dexPath) {
AssetManager assetManager = null;
try {
assetManager = AssetManager.class.newInstance();
Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);
addAssetPath.invoke(assetManager, dexPath);
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Resources resources = getResources();
mPluginResources = new Resources(assetManager, resources.getDisplayMetrics(),
resources.getConfiguration());
mPluginResources.newTheme().setTo(getTheme());
}
}
相關推薦
Android外掛技術——(三)載入未安裝apk
上一篇我們介紹了載入已安裝apk,本篇將介紹載入未安裝apk。 未安裝apk由於系統毫不知情,因此無法通過系統api獲取其上下文,自然也就無法獲取其資源。接下來,我們將另闢蹊徑來解決這個問題。 步驟如下: 一、採用上一篇中的Android Host工程,仍
Android熱補丁動態修復技術(三)—— 使用Javassist注入位元組碼,完成熱補丁框架雛形(可使用)
一、關於CSDN mardown編輯器的坑 Android熱補丁動態修復技術(三)這篇博文其實在4月8日的晚上已經發布了,然後緊接著寫第四篇,但是我將(四)儲存到草稿箱時,發現已經發布的(三)消失了,取而代之的是第四篇博文。 在論壇問過版主,可能是因為我誤操
從零開始學習音視頻編程技術(三) 開發環境搭建(Qt4.86手動設置環境,主要就是設置g++和qmake,比較透徹,附下載鏈接)
路徑 details 分享 baidu 末尾 是我 其中 找到 source 1.先下載安裝Qt 我們使用的版本是4.8。 可以自行百度下載也可以從下面的網盤地址下載: Qt庫和編譯器下載: 鏈接:http://pan.baidu.com/s/1hrUxLIG 密碼
中小型網絡最全的VLAN技術(三)——實現不同網段間通信——三層交換(路由)原理
三層交換 VLAN間通實現不同網段間通信 實驗概況: 如上兩圖所示,多vlan間通信建立在三層交換的基礎上,通過給虛擬vlan配置Ip網關,從而實現路由功能,實現不同VLAN間通信。如若跨多個VLAN或者路由器,則配置相應的靜態路由。原理解釋: 路由器的工作原理: 1.僅僅查看數據包中的IP地址中的目
Android Camera2 拍照(三)——切換攝像頭,延時拍攝和閃光模式
openca any The visible surface else 提示 再次 .cn 原文:Android Camera2 拍照(三)——切換攝像頭,延時拍攝和閃光模式
Android Studio 學習(三) 廣播
else set local activity .... order ... void test 動態註冊監聽網絡變化 創建intentFilter 並addAction 代表了監聽哪個廣播 然後使用registerReceiver()方法 將intentFilter 與
Android 開發:(三)安卓常用控制元件以及仿《微門戶》登入介面實現
一、常用控制元件: 1、文字類控制元件 TextView 負責展示文字,非編輯 EditText 可編輯文字控制元件 2、按鈕類控制元件 Button 按鈕 ImageButton 圖片按鈕 RadioButton與RadioGroup 單
谷歌三大核心技術(三)Google BigTable中文版
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
Docker核心技術(三)
Docker核心技術 Docker容器資料卷 Docker容器資料卷是什麼? Docker容器資料卷能幹嘛? Docker容器資料卷的實操 直接命令新增 DockerFile新增 資料卷容器
Android進階(三):Application啟動過程(最詳細&最簡單)
1.前言 最近一直在看 《Android進階解密》 的一本書,這本書編寫邏輯、流程都非常好,而且很容易看懂,非常推薦大家去看看(沒有收廣告費,單純覺得作者寫的很好)。 上一篇簡單的介紹了Android進階(二): 應用程序啟動過程,最終知道了ActivityThrea
PDF技術(三)-Java實現圖片轉PDF檔案
圖片轉pdf檔案同樣採用itext,將圖片加入即可 1)使用IText轉換 原理: 使用IText建立pdf,新增圖片。 優點: 速度快。 具體實現 public class Image2PDF { /*** @param picturePath 圖片地址*/
Android入門筆記(三)
三、RecyclerView、ViewHolder 和 Adapter 3.1 功能概括 RecyclerView :任務僅限於回收和定位螢幕上的 View,且其自身不會建立檢視,它建立的只是 ViewHolder。 ViewHolder:容納 View
Android開發筆記(三)螢幕解析度
在app編碼中經常需要獲取手機的螢幕解析度(寬*高),原來我直接上網拷貝程式碼,但在使用過程中卻發現諸多不便。 不便一:下面程式碼中的getWidth和getHeight在adt上提示deprecated已經廢棄了,實在扎眼 WindowManager wm = get
egret 釋出android原生專案(三)JS與原生通訊
JS與Java通訊 JS向Java傳送訊息 Java註冊接收訊息的方法: nativeAndroid.setExternalInterface("sendToNative", new INativePlayer.INativeInterface() { &n
Android輸入系統(三)InputReader的加工型別和InputDispatcher的分發過程
關聯絡列 解析WMS系列 深入理解JNI系列 輸入系統系列 前言 在上一篇文章中,我們學習了輸入事件的處理,輸入事件會交由InputDispatcher進行分發,那麼InputDispatcher是如何進行分發的?這篇文章會給你答案。 1.InputReader的加工型別 在Android輸入系統(二
Android Firebase接入(三)--Firebase 崩潰日誌報告(Crashlytics)
Firebase崩潰日誌報告可以自動記錄應用內崩潰資訊,只需簡單的幾步,就可以將Firebase Crashlytics新增到安卓工程中,然後Firebase Crashlytics就會自動的收集應用內崩潰資訊,包括錯誤型別,程式碼定位等等,非常的方便實用。 一、配置A
OpenGL(三) 載入貼圖
有了模型還需要貼圖。 載入貼圖 的流程大體分為兩部分,首先是圖片的解碼,其次是使用UV座標與模型對應。本文主要從底層原理和第三方庫兩個方面來介紹 載入貼圖 。解碼下面分別介紹硬編碼實現和SOIL庫兩種方式。硬編碼實現因為載入不同的型別圖片偏移值不一樣,載入圖片之前要確定圖片型
Android-json解析(三):原生JSONObject+JSONArray的解析、遍歷及生成等
一、JSONObject和JSONArray的資料表示形式 JSONObject的資料是用 { } 來表示的, 例如: { "id":"1", "courseID":"化學", "title":"滴定實驗",
一步一步開發Game伺服器(三)載入指令碼和伺服器熱更新
大家可能對遊戲伺服器的執行不太理解或者說不太清楚一些機制。 但是大家一定會明白一點,當程式在執行的時候出現一些bug,必須及時更新,但是不能重啟程式的情況下。 這裡牽涉到一個問題。比如說在遊戲裡面,,如果一旦開服,錯非完全致命性bug,否則是不能頻繁重啟伺服器程式的, 你重啟一次就可能流失一部分玩家。那
一步一步開發Game伺服器(三)載入指令碼和伺服器熱更新(二)完整版
可是在使用過程中,也許有很多會發現,動態載入dll其實不方便,應為需要預先編譯程式碼為dll檔案。便利性不是很高。 那麼有麼有辦法能做到動態實時更新呢???? 官方提供了這兩個物件,動態編譯原始檔。 提供對 C# 程式碼生成器和程式碼編譯器的例項的訪問。 CSharpCodeProvider