Android 备份(提取)apk
来源:互联网 发布:php淘宝短网址还原 编辑:程序博客网 时间:2024/06/07 12:27
本文介绍两种提取完整apk(系统预装的和用户安装的)
一、通过adb提取(适合开发者)
1. adb shell pm list packages找到要提取apk的包名
F:\winadb>adb shell pm list packagespackage:com.android.fmradiopackage:com.mediatek.gbapackage:com.mediatek.imspackage:com.android.cts.priv.ctsshimpackage:com.google.android.youtubepackage:org.simalliance.openmobileapi.uicc2terminalpackage:com.google.android.ext.servicespackage:com.android.providers.telephony...
2. adb shell pm path 定位apk所在系统路径
F:\winadb>adb shell pm path com.google.android.youtubepackage:/system/app/YouTube/YouTube.apk
3. adb pull <remote> [<local>] 从手机把apk pull下来
F:\winadb>adb pull /system/app/YouTube/YouTube.apk9745 KB/s (31047955 bytes in 3.111s)
二、app实现提取(适合大众)
比如坐高铁(或火车),看见隔壁的小伙伴玩的某款游戏,好像挺有意思,也想玩一下,好不容易向人家问到了,App名字,但是高速奔跑的高铁上没有WIFI,4G/3G网络(2G就不考虑了)又不好,怎么下载呢?如果能离线传输岂不更好?的确有,比如蓝牙、WIFI P2P(WIFI直连)都可以传输文件。这种情况还得apk在手机存储卡,否则也无法分享了。
下面就介绍通过app的方式将app(系统预装的和用户安装的)提取到手机存储(sdcard),实现的原理就像shell命令cp,java的实现是通过文件输入/输出流进行拷贝。(思路借鉴快牙app)
先上一张图,左边是快牙app,右边是本文说的demo
demo上面三个按钮用于过滤显示系统应用和用户自己安装的应用,每个item显示应用的图标、应用的名称、应用的包名、应用所在系统路径,一一对应,很容找到想要备份的apk了,长按弹出ContextMenu即可备份,代码比较简单,就一个类,直接贴出来了
package com.android.backupapp;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.nio.channels.FileChannel;import java.text.Collator;import java.util.ArrayList;import java.util.Collection;import java.util.Collections;import java.util.Comparator;import java.util.List;import com.android.backupapp.R.string;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.content.pm.ApplicationInfo;import android.content.pm.PackageInfo;import android.content.pm.PackageManager;import android.graphics.drawable.Drawable;import android.os.Build;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.os.UserHandle;import android.util.Log;import android.view.ContextMenu;import android.view.LayoutInflater;import android.view.MenuInflater;import android.view.MenuItem;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup;import android.view.ContextMenu.ContextMenuInfo;import android.view.View.OnCreateContextMenuListener;import android.widget.AdapterView;import android.widget.BaseAdapter;import android.widget.Button;import android.widget.ImageView;import android.widget.ListView;import android.widget.TextView;import android.widget.Toast;public class MainActivity extends Activity implements OnCreateContextMenuListener, OnClickListener { private PackageManager mPackageManager; private Button mBtnAllApps; private Button mBtnSystemApps; private Button mBtnDataApps; private ListView mListView; private AppListAdapter mAdapter; public int MID; private static final String BACKUP_PATH = "/sdcard/Backup/"; private static final String APK = ".apk"; private static final String ODEX = ".odex"; private static final String OAT32 = "oat/arm"; private static final String OAT64 = "oat/arm64"; public static enum AppType { SYSTEM, DATA, ALL } private static final int EVENT_COMPLETE = 1; private Handler mH = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case EVENT_COMPLETE: Toast.makeText(MainActivity.this, (String) msg.obj, Toast.LENGTH_SHORT).show(); break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mListView = (ListView) findViewById(R.id.listview); mListView.setOnCreateContextMenuListener(this); mBtnAllApps = (Button) findViewById(R.id.all_apps); mBtnSystemApps = (Button) findViewById(R.id.system_apps); mBtnDataApps = (Button) findViewById(R.id.data_apps); mBtnAllApps.setOnClickListener(this); mBtnSystemApps.setOnClickListener(this); mBtnDataApps.setOnClickListener(this); mPackageManager = getPackageManager(); List<PackageInfo> lists = mPackageManager .getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES); Collections.sort(lists, new DisplayNameComparator(mPackageManager)); mAdapter = new AppListAdapter(this, lists); mListView.setAdapter(mAdapter); } @Override public void onClick(View view) { // TODO Auto-generated method stub if (view == mBtnAllApps) { if (mAdapter.getAppType() != AppType.ALL) { mAdapter.setAppType(AppType.ALL); mAdapter.notifyDataSetChanged(); } } else if (view == mBtnSystemApps) { if (mAdapter.getAppType() != AppType.SYSTEM) { mAdapter.setAppType(AppType.SYSTEM); mAdapter.notifyDataSetChanged(); } } else if (view == mBtnDataApps) { if (mAdapter.getAppType() != AppType.DATA) { mAdapter.setAppType(AppType.DATA); mAdapter.notifyDataSetChanged(); } } } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { // TODO Auto-generated method stub MenuInflater inflater = new MenuInflater(this); inflater.inflate(R.menu.context_menu, menu); super.onCreateContextMenu(menu, v, menuInfo); } @Override public boolean onContextItemSelected(MenuItem item) { // TODO Auto-generated method stub AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item .getMenuInfo(); MID = (int) info.id; PackageInfo pi = mAdapter.getItem(MID); switch (item.getItemId()) { case R.id.backup: backupApp(pi); return true; } return super.onContextItemSelected(item); } private Drawable getAppIcon(PackageInfo packageInfo) { return packageInfo.applicationInfo.loadIcon(mPackageManager); } private String getAppName(PackageInfo packageInfo) { return packageInfo.applicationInfo.loadLabel(mPackageManager) .toString(); } private String getAppPackageName(PackageInfo packageInfo) { return packageInfo.packageName; } private String getAppSourceDir(PackageInfo packageInfo) { return packageInfo.applicationInfo.sourceDir; } private void backupApp(PackageInfo packageInfo) { String source = getAppSourceDir(packageInfo); if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { String key = getAppName(packageInfo); String dest = BACKUP_PATH + key + APK; Toast.makeText(this, R.string.backup_start, Toast.LENGTH_SHORT) .show(); new Thread(new CopyRunnable(source, dest, key)).start(); } else { String path = new File(source).getParent(); String name = new File(source).getName(); name = name.substring(0, name.indexOf(APK)); String kitKat = new File(path).getParent() + File.separator + name + ODEX; String oat32 = path + File.separator + OAT32 + File.separator + name + ODEX; String oat64 = path + File.separator + OAT64 + File.separator + name + ODEX; if (!new File(kitKat).exists() && !new File(oat32).exists() && !new File(oat64).exists()) { String key = getAppName(packageInfo); if (getAppIcon(packageInfo).equals( getAppPackageName(packageInfo))) { key = name; } String dest = BACKUP_PATH + key + APK; Toast.makeText(this, R.string.backup_start, Toast.LENGTH_SHORT) .show(); new Thread(new CopyRunnable(source, dest, key)).start(); } else { Toast.makeText(this, R.string.apk_has_oat, Toast.LENGTH_SHORT) .show(); } } } private class CopyRunnable implements Runnable { private String source; private String dest; private String key; public CopyRunnable(String source, String dest, String key) { this.source = source; this.dest = dest; this.key = key; } @Override public void run() { // TODO Auto-generated method stub try { int length = 1024 * 1024; if (!new File(BACKUP_PATH).exists()) { new File(BACKUP_PATH).mkdirs(); } File fDest = new File(dest); if (fDest.exists()) { fDest.delete(); } fDest.createNewFile(); FileInputStream in = new FileInputStream(new File(source)); FileOutputStream out = new FileOutputStream(fDest); FileChannel inC = in.getChannel(); FileChannel outC = out.getChannel(); int i = 0; while (true) { if (inC.position() == inC.size()) { inC.close(); outC.close(); Message message = mH.obtainMessage(EVENT_COMPLETE); message.obj = MainActivity.this.getString( R.string.backup_success, key, dest); mH.sendMessage(message); break; } if ((inC.size() - inC.position()) < 1024 * 1024) { length = (int) (inC.size() - inC.position()); } else { length = 1024 * 1024; } inC.transferTo(inC.position(), length, outC); inC.position(inC.position() + length); i++; } } catch (Exception e) { // TODO: handle exception Log.e("zhouyj", e.toString()); } } } private class AppListAdapter extends BaseAdapter { private Context context; private List<PackageInfo> lists; private AppType appType = AppType.DATA; public AppListAdapter(Context context, List<PackageInfo> lists) { this.context = context; this.lists = lists; } public AppType getAppType() { return appType; } public void setAppType(AppType appType) { this.appType = appType; } private List<PackageInfo> getDataList(AppType appType) { List<PackageInfo> l = new ArrayList<PackageInfo>(); switch (appType) { case SYSTEM: for (PackageInfo pi : lists) { if ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { l.add(pi); } } break; case DATA: for (PackageInfo pi : lists) { if ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { l.add(pi); } } break; case ALL: return lists; } return l; } @Override public int getCount() { // TODO Auto-generated method stub return getDataList(getAppType()).size(); } @Override public PackageInfo getItem(int position) { // TODO Auto-generated method stub return getDataList(getAppType()).get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub PackageInfo pi = getItem(position); ViewHolder viewHolder = null; if (convertView == null) { viewHolder = new ViewHolder(); LayoutInflater mInflater = LayoutInflater.from(context); convertView = mInflater.inflate(R.layout.layout_item, null); viewHolder.imageView = (ImageView) convertView .findViewById(R.id.drawable); viewHolder.tvAppName = (TextView) convertView .findViewById(R.id.app_name); viewHolder.tvPackageName = (TextView) convertView .findViewById(R.id.package_name); viewHolder.tvPath = (TextView) convertView .findViewById(R.id.app_path); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.imageView.setImageDrawable(getAppIcon(pi)); viewHolder.tvAppName.setText(getAppName(pi)); viewHolder.tvPackageName.setText(getAppPackageName(pi)); viewHolder.tvPath.setText(getAppSourceDir(pi)); return convertView; } } private static class ViewHolder { ImageView imageView; TextView tvAppName; TextView tvPackageName; TextView tvPath; } public static class DisplayNameComparator implements Comparator<PackageInfo> { public DisplayNameComparator(PackageManager pm) { mPM = pm; mCollator.setStrength(Collator.PRIMARY); } public final int compare(PackageInfo a, PackageInfo b) { // We want to put the one targeted to another user at the end of the // dialog. CharSequence sa = a.applicationInfo.loadLabel(mPM); if (sa == null) sa = a.packageName; CharSequence sb = b.applicationInfo.loadLabel(mPM); if (sb == null) sb = b.packageName; return mCollator.compare(sa.toString(), sb.toString()); } private final Collator mCollator = Collator.getInstance(); private PackageManager mPM; }}
Demo完整下载
阅读全文
0 0
- Android 备份(提取)apk
- android的apk文件的xml提取
- android的apk文件的xml提取
- 【Android】反编译apk,提取资源文件
- 【原创】反编译Android apk,提取*.…
- 提取apk
- Android备份:APK安装过程及原理
- 提取android apk文件中的dat格式的图片资源
- android反编译之apk资源提取-by TomHawk
- [android]提取系统应用(odex合并到apk)
- 提取apk文件
- 系统备份apk路径
- 反编译apk,提取资源文件
- Amdroid-APK-签名-证书提取
- android系统备份----即提取system.img和boot.img的方法!(转载)
- android系统备份----即提取system.img和boot.img的方法!(转载)
- 批量导出手机apk备份
- android apk
- hibernate插入数据到mysql数据库中乱码问题
- 判断网络的工具类
- JAVA课程学习十:继承训练
- 如何在 Azure 中均衡 Linux 虚拟机负载以创建高可用性应用程序
- Windows10专业版系统镜镜像
- Android 备份(提取)apk
- 块元素、内联元素、内联块特性
- sysbench压力测试
- layer常用功能代码
- Java跳出循环-break和continue语句
- 欢迎使用CSDN-markdown编辑器
- sql20171117
- 曲线来了,这里直接贴代码和github地址
- 批处理路径相关