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)


  这样三步就把想要的apk pull下来了,但是有个问题,执行第1步时,会dump很多包名,怎么确定那个包名是自己想要提取的apk吗?有些熟悉apk对应的包名一眼就认出来,但是对一个陌生的apk,是很难确定包名的。

二、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完整下载
原创粉丝点击