检测U盘中的apk文件并安装

项目背景 : 插上U盘后,自动识别扫描指定目录下的apk文件,并安装

1.监听U盘挂载

public final class USBReceiver extends BroadcastReceiver {
    private static final String TAG = "USBReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {
            AutoInstallService.checkAutoInstallFolder(context, "需要检测的U盘路径Path");
            Log.d(TAG, "U盘挂载");
        }
    }
}

2.安装

public class PackageManagerCompatP {
    private final static String TAG = PackageManagerCompatP.class.getSimpleName();
    private Context mContext;

    public PackageManagerCompatP(Context context) {
        this.mContext = context;
    }

    private PackageManager getPm() {
        return mContext.getPackageManager();
    }

    private PackageInstaller getPi() {
        return getPm().getPackageInstaller();
    }

    private void writeApkToInstallSession(PackageInstaller.Session session, String inPath,
                                          String splitName) throws RemoteException {
        long sizeBytes = 0;
        final File file = new File(inPath);
        if (file.isFile()) {
            sizeBytes = file.length();
        } else {
            return;
        }


        try (InputStream in = Files.newInputStream(Paths.get(inPath));
             OutputStream out = session.openWrite(splitName, 0, sizeBytes);) {

            int total = 0;
            byte[] buffer = new byte[65536];
            int c;
            while ((c = in.read(buffer)) != -1) {
                total += c;
                out.write(buffer, 0, c);
            }
            session.fsync(out);
        } catch (IOException e) {
            e.printStackTrace();
        } /*finally {
            session.close();
        }*/
    }

    public int invokeInstallPackage(String inPath, String pkg) {
        Log.d(TAG, "invokeInstallPackage inPath:" + inPath);
        PackageInstaller.Session session = null;
        try {
            final PackageInstaller.SessionParams sessionParams =
                    new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);
            sessionParams.installFlags = 0 | PackageManager.INSTALL_REPLACE_EXISTING;

            final int sessionId = getPi().createSession(sessionParams);
            session = getPi().openSession(sessionId);
            writeApkToInstallSession(session, inPath, pkg);
            final LocalIntentReceiver localReceiver = new LocalIntentReceiver();
            session.commit(localReceiver.getIntentSender());
            final Intent result = localReceiver.getResult();
            final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
                    PackageInstaller.STATUS_FAILURE);
            Log.d(TAG, "get install state:" + status);
            session.close();
            session = null;
            if (status != PackageInstaller.STATUS_SUCCESS) {
                Log.e(TAG, "Installation should have succeeded, but got code "
                        + status);
            } else {
                Log.e(TAG, "Installation  have succeeded");
            }
            return status;
        } catch (IllegalArgumentException | IOException | RemoteException e) {
            Log.e(TAG, "Failed to install package; path=" + inPath, e);
        } finally {
            if (session != null) {
                session.close();
            }
        }

        return PackageInstaller.STATUS_FAILURE;
    }

    private static class LocalIntentReceiver {
        private final SynchronousQueue<Intent> mResult = new SynchronousQueue<>();
        private final IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
            @Override
            public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
                             IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
                try {
                    mResult.offer(intent, 5, TimeUnit.SECONDS);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        };

        public IntentSender getIntentSender() {
            return new IntentSender((IIntentSender) mLocalSender);
        }

        public Intent getResult() {
            try {
                return mResult.take();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

}

public class AutoInstallService extends Service {
    private static final String TAG = AutoInstallService.class.getSimpleName();
    public final static String AUTO_INSTALL_FOLDER = "AutoInstall";
    public final static String EXTRA_USB_PATH = "extra_usb_path";
    public AutoInstallService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return null;
    }

    public static void checkAutoInstallFolder(Context context, final String path) {
        Log.d(TAG, "installFolderExists path:" + path);
        if (!TextUtils.isEmpty(path)) {
            String installPath = path.endsWith(File.separator) ?
                    path + AUTO_INSTALL_FOLDER : path + File.separator + AUTO_INSTALL_FOLDER;
            if (new File(installPath).exists()) {
                Intent intent = new Intent(context, AutoInstallService.class);
                intent.putExtra(EXTRA_USB_PATH, path);
                context.startServiceAsUser(intent, UserHandle.CURRENT);
            }
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        String path = intent.getStringExtra(EXTRA_USB_PATH);
        Log.d(TAG, "onStartCommand path:" + path + " intent:" + intent);
        if (!TextUtils.isEmpty(path)) {
            String installPath = path.endsWith(File.separator) ?
                    path + AUTO_INSTALL_FOLDER : path + File.separator + AUTO_INSTALL_FOLDER;
            File usb = new File(installPath);
            Log.d(TAG, "installPath:" + installPath + " exists:" + usb.exists());
            if (usb.exists()) {
                File[] list = usb.listFiles((file, name) -> name.endsWith(".apk") || name.endsWith(".APK"));
//                new Handler().post(new InstallTask(getApplicationContext(), list));
                new Thread(new InstallTask(getApplicationContext(), list, new MsgHandler(this))).start();
            }
        }
        return Service.START_NOT_STICKY;
    }

    private static final class InstallTask implements Runnable {
        private final File[] mApkList;
        private final PackageManagerCompatP mPMCP;
        private final Context mContext;
        private final MsgHandler mHandler;
        public InstallTask(Context context, File[] list, MsgHandler handler) {
            mApkList = list;
            mPMCP = new PackageManagerCompatP(context);
            mContext = context;
            mHandler = handler;
        }

        @Override
        public void run() {
            Log.d(TAG, "InstallTask list:" + mApkList + " size:" + (mApkList == null ? 0 : mApkList.length));
            if (mApkList != null) {
                mHandler.sendMessage(
                        mHandler.obtainMessage(MsgHandler.WHAT_DIALOG_SHOW,
                                "现在开始安装,总共有" + mApkList.length + "个APK待安装!"));


                for (File file : mApkList) {
                    Log.d(Thread.currentThread().getName(), "start to install file:" + file.getAbsolutePath());
                    PackageInfo info = mContext.getPackageManager().getPackageArchiveInfo(file.getAbsolutePath(),
                            PackageManager.GET_ACTIVITIES | PackageManager.GET_SERVICES);
                    /*mHandler.sendMessage(
                            mHandler.obtainMessage(MsgHandler.WHAT_UPDATE_DIALOG_MESSAGE,
                                    String.format("应用(%s)正在安装中...", info.packageName)));*/

                    int status = mPMCP.invokeInstallPackage(file.getAbsolutePath(), info.packageName);
                    String msg = String.format("安装应用(%s)%s!",
                            info.packageName, status == PackageInstaller.STATUS_SUCCESS ? "成功" : "失败");
                    if (status != PackageInstaller.STATUS_SUCCESS) {
                        mHandler.sendMessage(mHandler.obtainMessage(MsgHandler.WHAT_UPDATE_DIALOG_MESSAGE, msg));
                    }
                }

                mHandler.sendMessage(
                        mHandler.obtainMessage(MsgHandler.WHAT_UPDATE_DIALOG_MESSAGE,
                                "所有应用安装已经完成,请到\"我的应用\"中查看!"));
                mHandler.sendEmptyMessageDelayed(MsgHandler.WHAT_DIALOG_DISMISS, 10 * 1000L);
            }

            mContext.stopServiceAsUser(new Intent(mContext, AutoInstallService.class), UserHandle.CURRENT);
        }
    }

    private static final class MsgHandler extends Handler {
        private static final int WHAT_UPDATE_DIALOG_MESSAGE = 10086;
        private static final int WHAT_DIALOG_SHOW = 10010;
        private static final int WHAT_DIALOG_DISMISS = 10011;
        private final WeakReference<AutoInstallService> mBase;

        public MsgHandler(AutoInstallService service) {
            mBase = new WeakReference<>(service);
        }

        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case WHAT_UPDATE_DIALOG_MESSAGE:
                    mBase.get().updateDialogMessage((String) msg.obj);
                    break;
                case WHAT_DIALOG_SHOW:
                    mBase.get().showDialog((String) msg.obj);
                    break;
                case WHAT_DIALOG_DISMISS:
                    if (mBase.get() != null) {
                        mBase.get().dismissDialog();
                    }
                    break;
            }
        }
    }

    private AlertDialog mDialog;
    private void showDialog(String msg) {
        /*if (mDialog == null) {
            mDialog = new AlertDialog.Builder(this)
                    .setTitle("注意")
                    .setMessage(msg)
                    .setNegativeButton("确定", (dialogInterface, i) -> dialogInterface.dismiss())
                    .create();
            mDialog.getWindow().setType(TYPE_SYSTEM_ALERT);
        } else {
            mDialog.setMessage(msg);
        }
        mDialog.show();*/
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
    }
    private void dismissDialog() {
        if (mDialog != null) {
            mDialog.dismiss();
        }
    }

    private void updateDialogMessage(String msg) {
        /*mDialog.setMessage(msg);
        if (!mDialog.isShowing()) {
            mDialog.show();
        }*/
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值