Android動態載入(一)--載入已經安裝的APK
阿新 • • 發佈:2019-02-05
接下來再來看看怎麼使用Intent元件啟動被呼叫工程: [java] view plaincopyprint?
最近在研究Android動態載入APK技術,偶有小得,共享一下,歡迎交流。
首先是Android 動態載入已安裝的APK
截圖:
被呼叫工程TestB:
其工程已添加了字串、顏色和圖片資源,這裡不寫了,讀者可自行新增。
[java] view plaincopyprint?- publicclass TestBActivity extends Activity{
- /** Called when the activity is first created. */
- @Override
- publicvoid onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- Button button=(Button)findViewById(R.id.button1);
- button.setOnClickListener(new OnClickListener() {
- @Override
- publicvoid onClick(View v) {
- // TODO Auto-generated method stub
- Toast.makeText(TestBActivity.this, "this is testB", Toast.LENGTH_SHORT).show();
- }
- });
- }
- }
public class TestBActivity extends Activity{ /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button button=(Button)findViewById(R.id.button1); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub Toast.makeText(TestBActivity.this, "this is testB", Toast.LENGTH_SHORT).show(); } }); } }
接著把TestB打包為TestB.apk,放到sdcard的根目錄。
呼叫工程TestA:首先應該是安裝apk檔案:
[java] view plaincopyprint?- protectedvoid InstallAPK(String apkname) {
- // TODO Auto-generated method stub
- //程式碼安裝
- String fileName = Environment.getExternalStorageDirectory() + "/"+apkname;
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- // intent.setDataAndType(Uri.parse("file://"+fileName), "application/vnd.android.package-archive");
- intent.setDataAndType(Uri.fromFile(new File(fileName)), "application/vnd.android.package-archive");
- TestAActivity.this.startActivityForResult(intent, 1);
protected void InstallAPK(String apkname) {
// TODO Auto-generated method stub
//程式碼安裝
String fileName = Environment.getExternalStorageDirectory() + "/"+apkname;
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// intent.setDataAndType(Uri.parse("file://"+fileName), "application/vnd.android.package-archive");
intent.setDataAndType(Uri.fromFile(new File(fileName)), "application/vnd.android.package-archive");
TestAActivity.this.startActivityForResult(intent, 1);
但是安裝之前是不是要先檢測一下TestB.apk是否已安裝呢:
[java] view plaincopyprint?- protectedboolean checkInstall(String pak) {
- // TODO Auto-generated method stub
- boolean install=false;
- PackageManager pm=getPackageManager();
- try {
- PackageInfo info=pm.getPackageInfo(pak,1);
- if (info!=null&&info.activities.length>0) {
- install=true;
- }
- } catch (NameNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return install;
- }
protected boolean checkInstall(String pak) {
// TODO Auto-generated method stub
boolean install=false;
PackageManager pm=getPackageManager();
try {
PackageInfo info=pm.getPackageInfo(pak,1);
if (info!=null&&info.activities.length>0) {
install=true;
}
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return install;
}
如果未安裝,便呼叫InstallAPK(String apkname)安裝,如果已安裝便可程式碼獲取其資源:
[java] view plaincopyprint?- privatevoid getRes(String pak){
- if (checkInstall(pak)) {
- try {
- Context ctxTestB = getTestContext(pak);
- Resources res = ctxTestB.getResources();
- // 獲取字串string
- String hello = res.getString(getId("string", "hello", pak));
- ((TextView) findViewById(R.id.testb_string)).setText(hello);
- // 獲取圖片Drawable
- Drawable drawable = res.getDrawable(getId("drawable", "testb",pak));
- ((ImageView) findViewById(R.id.testb_drawable)).setImageDrawable(drawable);
- // 獲取顏色值
- int color = res.getColor(getId("color", "white",pak));
- ((TextView) findViewById(R.id.testb_color)).setBackgroundColor(color);
- // 獲取佈局檔案
- View view = getView(ctxTestB, getId("layout", "main",pak));
- LinearLayout layout = (LinearLayout) findViewById(R.id.testb_layout);
- layout.addView(view);
- } catch (NameNotFoundException e) {
- e.printStackTrace();
- }}
- }
- //獲取資源對應的編號
- privateint getId(String name, String type,String pak) {
- return testb.getIdentifier(name, type, pak);
- }
- // 獲取檢視
- public View getView(Context ctx, int id) {
- return ((LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(id,null);
- }
- //獲取TestB的Context
- private Context getTestContext(String pak) throws NameNotFoundException {
- return createPackageContext(pak,Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE);
- }
private void getRes(String pak){
if (checkInstall(pak)) {
try {
Context ctxTestB = getTestContext(pak);
Resources res = ctxTestB.getResources();
// 獲取字串string
String hello = res.getString(getId("string", "hello", pak));
((TextView) findViewById(R.id.testb_string)).setText(hello);
// 獲取圖片Drawable
Drawable drawable = res.getDrawable(getId("drawable", "testb",pak));
((ImageView) findViewById(R.id.testb_drawable)).setImageDrawable(drawable);
// 獲取顏色值
int color = res.getColor(getId("color", "white",pak));
((TextView) findViewById(R.id.testb_color)).setBackgroundColor(color);
// 獲取佈局檔案
View view = getView(ctxTestB, getId("layout", "main",pak));
LinearLayout layout = (LinearLayout) findViewById(R.id.testb_layout);
layout.addView(view);
} catch (NameNotFoundException e) {
e.printStackTrace();
}}
}
//獲取資源對應的編號
private int getId(String name, String type,String pak) {
return testb.getIdentifier(name, type, pak);
}
// 獲取檢視
public View getView(Context ctx, int id) {
return ((LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(id,null);
}
//獲取TestB的Context
private Context getTestContext(String pak) throws NameNotFoundException {
return createPackageContext(pak,Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE);
}
接下來再來看看怎麼使用Intent元件啟動被呼叫工程: [java] view plaincopyprint?
- protectedvoid startAPK(String pak) {
- // TODO Auto-generated method stub
- //程式碼啟動
- try {
- //pak=PACKAGE_TEST_B+".TestBActivity"
- Context ctxTestB = getTestContext(PACKAGE_TEST_B);
- Class cls = ctxTestB.getClassLoader().loadClass(pak);
- TestAActivity.this.startActivity(new Intent(ctxTestB, cls));
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } catch (NameNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
protected void startAPK(String pak) {
// TODO Auto-generated method stub
//程式碼啟動
try {
//pak=PACKAGE_TEST_B+".TestBActivity"
Context ctxTestB = getTestContext(PACKAGE_TEST_B);
Class cls = ctxTestB.getClassLoader().loadClass(pak);
TestAActivity.this.startActivity(new Intent(ctxTestB, cls));
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
以下為擴充套件內容:
比如加上網路下載apk檔案功能,然後再安裝,這裡使用的是URL通訊協議,用HttpURLConnection類,面向的是應用層:
[java] view plaincopyprint?- protected File downLoadFile(String httpUrl) {
- // TODO Auto-generated method stub
- String filename="down_TestB.apk";
- File file=new File(Environment.getExternalStorageDirectory() + "/"+filename);
- try {
- URL url = new URL(httpUrl);
- try {
- HttpURLConnection conn = (HttpURLConnection) url
- .openConnection();
- InputStream is = conn.getInputStream();
- FileOutputStream fos = new FileOutputStream(file);
- byte[] buf = newbyte[256];
- conn.connect();
- int count = 0;
- if (conn.getResponseCode()==200) {
- while ((count=is.read(buf))>0) {
- fos.write(buf, 0, count);
- }
- }
- conn.disconnect();
- fos.close();
- is.close();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } catch (MalformedURLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return file;
- }
protected File downLoadFile(String httpUrl) {
// TODO Auto-generated method stub
String filename="down_TestB.apk";
File file=new File(Environment.getExternalStorageDirectory() + "/"+filename);
try {
URL url = new URL(httpUrl);
try {
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
InputStream is = conn.getInputStream();
FileOutputStream fos = new FileOutputStream(file);
byte[] buf = new byte[256];
conn.connect();
int count = 0;
if (conn.getResponseCode()==200) {
while ((count=is.read(buf))>0) {
fos.write(buf, 0, count);
}
}
conn.disconnect();
fos.close();
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return file;
}
此工程還可擴充套件,比如獲取未安裝apk或者已安裝apk的版本、圖示等資源,和已安裝的apk進行版本比較,以確定是否要升級新版本。關於此可以看下我的另一篇博文《Android獲取未安裝和已安裝apk的版本、圖示等資源》。