USBService源码分析之Usb权限(二)

来源:互联网 发布:散打 知乎 编辑:程序博客网 时间:2024/05/11 01:20

1、背景

前面一篇文章中我们分析了USBService在Android系统中的创建方式USBService源码分析(一),相信通过上一篇文章的阐述大家对其也有一定的了解了,今天就来和大家来谈谈usb权限的问题。

在用PC连接Android设备,使用adb devices查看手机是否连接时,手机端会弹出权限提醒框,提醒用户赋予权限,接下来我们就来看看Android系统是如何弹出这个选择框的。

2、源码分析

这里我们就从UsbService开始分析,手机弹出权限对话框首先从USBService的以下方法开始的。

public class UsbService extends IUsbManager.Stub {    public void requestDevicePermission(UsbDevice device, String packageName, PendingIntent pi) {        final int userId = UserHandle.getCallingUserId();        //调用UsbSettingsManager的requestPermission()方法        getSettingsForUser(userId).requestPermission(device, packageName, pi);    }}

我们进入UsbSettingsManager的requestPermission()方法发现,其最终调用本类的requestPermissionDialog()方法,我们进入该方法。

private void requestPermissionDialog(Intent intent, String packageName, PendingIntent pi) {        final int uid = Binder.getCallingUid();        try {            ApplicationInfo aInfo = mPackageManager.getApplicationInfo(packageName, 0);            if (aInfo.uid != uid) {                throw new IllegalArgumentException("package " + packageName +                        " does not match caller's uid " + uid);            }        } catch (PackageManager.NameNotFoundException e) {            throw new IllegalArgumentException("package " + packageName + " not found");        }        long identity = Binder.clearCallingIdentity();        //启动SystemUI应用的UsbPermissionActivity界面        intent.setClassName("com.android.systemui",                "com.android.systemui.usb.UsbPermissionActivity");        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        intent.putExtra(Intent.EXTRA_INTENT, pi);        intent.putExtra("package", packageName);        intent.putExtra(Intent.EXTRA_UID, uid);        try {            mUserContext.startActivityAsUser(intent, mUser);        } catch (ActivityNotFoundException e) {            Slog.e(TAG, "unable to start UsbPermissionActivity");        } finally {            Binder.restoreCallingIdentity(identity);        }    }

文中注释部分很重要,这里直接来启动SystemUI应用的UsbPermissionActivity界面,在看这个类的源码之前,我们看一下其具体位置。

frameworks/base/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java<string name="usb_device_permission_prompt" msgid="834698001271562057">"允许应用“<xliff:g id="APPLICATION">%1$s</xliff:g>”访问该USB设备吗?"</string><string name="always_use_device" msgid="1450287437017315906">"默认情况下用于该USB设备"</string>

好啦,接下来我们直接进入UsbPermissionActivity的源码。

public class UsbPermissionActivity extends AlertActivity        implements DialogInterface.OnClickListener, CheckBox.OnCheckedChangeListener {    public void onCreate(Bundle icicle) {        super.onCreate(icicle);       Intent intent = getIntent();        mDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);        mAccessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);        mPendingIntent = (PendingIntent)intent.getParcelableExtra(Intent.EXTRA_INTENT);        mUid = intent.getIntExtra(Intent.EXTRA_UID, -1);        //包名        mPackageName = intent.getStringExtra("package");        PackageManager packageManager = getPackageManager();        ApplicationInfo aInfo;        try {            aInfo = packageManager.getApplicationInfo(mPackageName, 0);        } catch (PackageManager.NameNotFoundException e) {            Log.e(TAG, "unable to look up package name", e);            finish();            return;        }        String appName = aInfo.loadLabel(packageManager).toString();}

这段代码是获取应用的包名,我们可以通过包名对比来决定是否弹出对话框。

final AlertController.AlertParams ap = mAlertParams;        ap.mIcon = aInfo.loadIcon(packageManager);        ap.mTitle = appName;        if (mDevice == null) {            ap.mMessage = getString(R.string.usb_accessory_permission_prompt, appName);            mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mAccessory);        } else {            ap.mMessage = getString(R.string.usb_device_permission_prompt, appName);            mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mDevice);        }        ap.mPositiveButtonText = getString(android.R.string.ok);        ap.mNegativeButtonText = getString(android.R.string.cancel);        ap.mPositiveButtonListener = this;        ap.mNegativeButtonListener = this;        // add "always use" checkbox        LayoutInflater inflater = (LayoutInflater)getSystemService(                Context.LAYOUT_INFLATER_SERVICE);        ap.mView = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null);        mAlwaysUse = (CheckBox)ap.mView.findViewById(com.android.internal.R.id.alwaysUse);        if (mDevice == null) {            mAlwaysUse.setText(R.string.always_use_accessory);        } else {            mAlwaysUse.setText(R.string.always_use_device);        }        mAlwaysUse.setOnCheckedChangeListener(this);        mClearDefaultHint = (TextView)ap.mView.findViewById(                                                    com.android.internal.R.id.clearDefaultHint);        mClearDefaultHint.setVisibility(View.GONE);        //这个方法重要        setupAlert();

以上代码就是弹出的对话框,如果我们想让应用不弹出这样的对话框,可以做以下修改。

//(1)某个应用不弹出权限对话框if(!mPackageName.equals("com.vaultmicro.camerafi"))//权限包名     setupAlert();else {    mPermissionGranted = true;    finish();}//(2)所有应用都不弹出对话框//setupAlert();//不使用窗口mPermissionGranted = true;finish();

这种处理方法来自这个文件的按钮点击相应事件。

public void onClick(DialogInterface dialog, int which) {        if (which == AlertDialog.BUTTON_POSITIVE) {            mPermissionGranted = true;        }        finish();    }

好啦,到此整个UsbService以及usb弹出权限框的问题就简单阐述到这里啦。

0 0
原创粉丝点击