Uiautomator

问题:在android studio中使用UiAutomator 2.0 编写测试用例时,要实现截图(非命令方式),写入文件时出现权限被拒绝的提示。例如:

java.io.FileNotFoundException: /storage/emulated/0/uidump.xml (Permission denied)

注:通过命令的方式进行截图/创建文件不会出现权限受限问题,凡是通过IO流、File类进行文件读写等方式的操作,都需要添加权限并打开权限,才能正常运行成功。

解决:在当前测试脚本所在的 module的AndroidManifest.xml文件中添加读写权限

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>

你以为只要添加以上权限就够了吗?NO,那仅仅是添加了该app的读写权限而已,并没有打开权限,所以还是被拒绝的。下面则通过几种方式进行打开权限:

1.手动打开权限:设置->应用->目标应用->权限->存储 。打开该权限即可。

2.脚本中打开权限:通过UI界面操作打开 或者 使用命令进行打开。这里用命令的方式打开权限。

adb shell pm grant 包名 权限

adb shell pm grant com.android.contacts android.permission.READ_EXTERNAL_STORAGE

adb shell pm grant com.android.contacts android.permission.WRITE_EXTERNAL_STORAGE

 顺便这里提及一下查看包名和权限命令(adb命令那篇中也有):

那么Uiautomator脚本中怎么写呢?(这是最直接的写法。如果有多个权限,可以通过Android API获取程序的所有权限,然后再打开所有权限即可)

UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
  .executeShellCommand("pm grant com.android.contacts android.permission.READ_EXTERNAL_STORAGE");

写一个工具类来打开权限

package com.zzw.systemutils;

import android.app.Instrumentation;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.support.annotation.Nullable;
import android.support.test.InstrumentationRegistry;
import android.support.test.uiautomator.UiDevice;
import android.util.Log;

import junit.framework.Assert;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by pc-zzw on 2017/12/4.
 * 权限处理 SDK >= M
 * pm list permissions : All Permissions
 * pm list permission-groups : All Permission Groups
 */

public class Permissions {
    private static Instrumentation instrument= InstrumentationRegistry.getInstrumentation();
    private static UiDevice mDevice= UiDevice.getInstance(instrument);

    /**
     * grant 命令处理当前程序(module app)的权限
     * @param permission such as : android.permission.WRITE_EXTERNAL_STORAGE
     * @throws IOException IO
     */
    public static void grantCurrentPermission(String permission) throws IOException {
        grantPermission(instrument.getTargetContext().getPackageName(),permission);
    }

    /**
     * grant 命令处理当前程序(module app)的所有权限
     * @throws IOException IO
     */
    public static void grantCurrentAllPermissions() throws IOException {
        grantAllPermissions(instrument.getTargetContext().getPackageName());
    }

    /**
     * grant 命令处理应用的权限
     * @param packageName such as : com.zzw.testdome
     * @param permission such as : android.permission.WRITE_EXTERNAL_STORAGE
     * @throws IOException IO
     */
    public static void grantPermission(String packageName , String permission) throws IOException {
        Assert.assertNotNull(packageName);
        Assert.assertNotNull(permission);
        Log.e("grantPermission: ",packageName+" "+permission);
        String cmd = String.format("pm grant %s %s",packageName , permission);
        String result = mDevice.executeShellCommand(cmd);
        Assert.assertTrue(result == null || !result.contains("Err"));
    }

    /**
     * 使用命令处理应用的所有权限
     * @param packageName Application Package Name
     */
    public static void grantAllPermissions(String packageName) throws IOException {
        Context context=instrument.getTargetContext();
        PackageInfo packageInfo = getPackageInfo(context, packageName);
        String[] permissions ;
        if (packageInfo != null) {
            permissions = packageInfo.requestedPermissions;
            permissions = extractUnGranted(context, packageName, permissions);
            if(permissions == null) return;
            for (String p : permissions) {
                Log.i("grantAllPermissions: ",packageName+"----"+p);
                grantPermission(packageName, p);
            }
        }
    }

    //提取未授权的权限
    private static String [] extractUnGranted(Context context,String packageName,String[] declaredPerms){
        if (declaredPerms == null || declaredPerms.length == 0) return null;
        PackageManager packageManager = context.getPackageManager();
        List<String> requestList = new ArrayList<>(declaredPerms.length);
        for (String permName : declaredPerms) {
            // 检查权限是否已授权
            int code = packageManager.checkPermission(permName, packageName);
            if (code == PackageManager.PERMISSION_GRANTED) continue;
            requestList.add(permName);
        }
        String[] unGranted = new String[requestList.size()];
        for (int i = 0; i < requestList.size(); i++) {
            unGranted[i] = requestList.get(i);
        }
        return unGranted;
    }

    //获取包的权限信息
    @Nullable
    private static PackageInfo getPackageInfo(Context context, String packageName){
        PackageManager packageManager = context.getPackageManager();
        try {
            return packageManager.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
        } catch (PackageManager.NameNotFoundException e) {
            return null;
        }
    }
}
View Code

最后这里贴出官网上系统权限部分>>>>>>>>>>>>

原文地址:https://www.cnblogs.com/zeo-to-one/p/8322114.html