当前位置: 首页 > news >正文

珠海门户网站建设多少钱seo培训一对一

珠海门户网站建设多少钱,seo培训一对一,上海金融网站制作网站制作公司好,微网站建设市场1. 前言 继上一篇文章说到Android权限汇总, 请移步笔者的文章Android 权限(一):权限大全_broadview_java的博客-CSDN博客_android 仅使用中允许权限 先要理清楚权限分类和定义,本篇文章继续说一下动态权限的申请和框架层的实现流程, 以及如何实现赋予系统应用默认的…

1. 前言

        继上一篇文章说到Android权限汇总, 请移步笔者的文章Android 权限(一):权限大全_broadview_java的博客-CSDN博客_android 仅使用中允许权限

先要理清楚权限分类和定义,本篇文章继续说一下动态权限的申请和框架层的实现流程, 以及如何实现赋予系统应用默认的权限的需求.

2. 动态权限申请

        在Android6.0之后,  在首次打开app时的时候,比如微信,钉钉等软件时,会有提示

1)有读取设备上的照片及文字

2)获取手机号,IMEI,IMSI 

3)获取设备的定位信息 

等权限申请的对话框, 需要我们通过手动点击确认.

我们来一步一步分析对话框显示的原理和流程

2.1 检查权限

我们来通过一个Demo演示一下, Activity中的代码如下

public class MainActivity extends AppCompatActivity {private static final int REQUEST_CODE_TEST = 1024;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {if(this.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {Toast.makeText(this, "请申请权限", Toast.LENGTH_LONG).show();//申请权限的代码// ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE_TEST);requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE_TEST);}}}//回调方法@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);android.util.Log.e("test", "====int requestCode==== :" + requestCode+ " 具体的 permission :" + permissions[0] + "\n"+ "== grantResults数组长度 : " + grantResults.length + "====grantResults对应的int 值:" + grantResults[0]);}
}

代码讲解:

checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) 这个方法是检测是否有具有READ_EXTERNAL_STORAGE 此权限, 返回值 :

    /*** Permission check result: this is returned by {@link #checkPermission}* if the permission has been granted to the given package.*/public static final int PERMISSION_GRANTED = 0;/*** Permission check result: this is returned by {@link #checkPermission}* if the permission has not been granted to the given package.*/public static final int PERMISSION_DENIED = -1;

0:表示已获取该权限,  -1:表示未赋予该权限

我是用Android 10源码追溯的流程,我们来看看此代码的调用流程:

1. frameworks/base/core/java/android/content/ContextWrapper.java

    @Overridepublic int checkSelfPermission(String permission) {return mBase.checkSelfPermission(permission);}

2.frameworks/base/core/java/android/content/Context.java

    @PackageManager.PermissionResultpublic abstract int checkSelfPermission(@NonNull String permission);

3. 我们继续看看Context 的实现类 ContextImpl.java

frameworks/base/core/java/android/app/ContextImpl.java

    @Overridepublic int checkSelfPermission(String permission) {if (permission == null) {throw new IllegalArgumentException("permission is null");}return checkPermission(permission, Process.myPid(), Process.myUid());}

4.紧接着跳转到 ActivityManagerService.java中的方法

    @Overridepublic int checkPermission(String permission, int pid, int uid) {if (permission == null) {return PackageManager.PERMISSION_DENIED;}return checkComponentPermission(permission, pid, uid, -1, true);}public static int checkComponentPermission(String permission, int pid, int uid,int owningUid, boolean exported) {if (pid == MY_PID) {return PackageManager.PERMISSION_GRANTED;}return ActivityManager.checkComponentPermission(permission, uid,owningUid, exported);}

5.接着继续调用ActivityManager.java文件中的checkComponentPermission方法

public static int checkComponentPermission(String permission, int uid,int owningUid, boolean exported) {//省略......................try {return AppGlobals.getPackageManager().checkUidPermission(permission, uid);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}

6.继续调用到 PackageManagerService.java中的checkUidPermission方法

    public int checkUidPermission(String permName, int uid) {final CheckPermissionDelegate checkPermissionDelegate;synchronized (mPackages) {if (mCheckPermissionDelegate == null)  {return checkUidPermissionImpl(permName, uid);}checkPermissionDelegate = mCheckPermissionDelegate;}return checkPermissionDelegate.checkUidPermission(permName, uid,PackageManagerService.this::checkUidPermissionImpl);}private int checkUidPermissionImpl(String permName, int uid) {synchronized (mPackages) {final String[] packageNames = getPackagesForUid(uid);PackageParser.Package pkg = null;final int N = packageNames == null ? 0 : packageNames.length;for (int i = 0; pkg == null && i < N; i++) {pkg = mPackages.get(packageNames[i]);}return mPermissionManager.checkUidPermission(permName, pkg, uid, getCallingUid());}}

7. 接下来继续调用 PermissionManagerService.java去

        public int checkUidPermission(String permName, PackageParser.Package pkg, int uid,int callingUid) {return PermissionManagerService.this.checkUidPermission(permName, pkg, uid, callingUid);}//这里是最终返回判断值的方法
private int checkUidPermission(String permName, PackageParser.Package pkg, int uid,int callingUid) {final int callingUserId = UserHandle.getUserId(callingUid);final boolean isCallerInstantApp =mPackageManagerInt.getInstantAppPackageName(callingUid) != null;final boolean isUidInstantApp =mPackageManagerInt.getInstantAppPackageName(uid) != null;final int userId = UserHandle.getUserId(uid);if (!mUserManagerInt.exists(userId)) {return PackageManager.PERMISSION_DENIED;}if (pkg != null) {if (pkg.mSharedUserId != null) {if (isCallerInstantApp) {return PackageManager.PERMISSION_DENIED;}} else if (mPackageManagerInt.filterAppAccess(pkg, callingUid, callingUserId)) {return PackageManager.PERMISSION_DENIED;}final PermissionsState permissionsState =((PackageSetting) pkg.mExtras).getPermissionsState();if (permissionsState.hasPermission(permName, userId)) {if (isUidInstantApp) {if (mSettings.isPermissionInstant(permName)) {return PackageManager.PERMISSION_GRANTED;}} else {return PackageManager.PERMISSION_GRANTED;}}if (isImpliedPermissionGranted(permissionsState, permName, userId)) {return PackageManager.PERMISSION_GRANTED;}} else {ArraySet<String> perms = mSystemPermissions.get(uid);if (perms != null) {if (perms.contains(permName)) {return PackageManager.PERMISSION_GRANTED;}if (FULLER_PERMISSION_MAP.containsKey(permName)&& perms.contains(FULLER_PERMISSION_MAP.get(permName))) {return PackageManager.PERMISSION_GRANTED;}}}return PackageManager.PERMISSION_DENIED;}

这里是最终判断返回值的方法,  好了,到这里阶段一就完成了. 如果返回PERMISSION_GRANTED, 那没啥事情了, 如果返回PERMISSION_DENIED, 那你就得去动态申请了, 动态申请权限不多,就是固定的几组(在上一篇文章中以介绍说明).   android系统也为我们设计好了动态申请权限的对话框. 我们来说一下它的显示流程.

2.2 申请权限

申请权限是requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE_TEST)方法实现的

1. 跳转到Activity.java中的requestPermissions方法

frameworks/base/core/java/android/app/Activity.java

    public final void requestPermissions(@NonNull String[] permissions, int requestCode) {if (requestCode < 0) {throw new IllegalArgumentException("requestCode should be >= 0");}if (mHasCurrentPermissionsRequest) {Log.w(TAG, "Can request only one set of permissions at a time");// Dispatch the callback with empty arrays which means a cancellation.onRequestPermissionsResult(requestCode, new String[0], new int[0]);return;}//创建跳转的目标activityIntent intent = getPackageManager().buildRequestPermissionsIntent(permissions);startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);mHasCurrentPermissionsRequest = true;}

2. 注意一下此段代码:buildRequestPermissionsIntent(permissions)

frameworks/base/core/java/android/content/pm/PackageManager.java

    @NonNull@UnsupportedAppUsagepublic Intent buildRequestPermissionsIntent(@NonNull String[] permissions) {if (ArrayUtils.isEmpty(permissions)) {throw new IllegalArgumentException("permission cannot be null or empty");}Intent intent = new Intent(ACTION_REQUEST_PERMISSIONS);intent.putExtra(EXTRA_REQUEST_PERMISSIONS_NAMES, permissions);intent.setPackage(getPermissionControllerPackageName());return intent;}
@SystemApi
public static final String ACTION_REQUEST_PERMISSIONS ="android.content.pm.action.REQUEST_PERMISSIONS";

通过这个ACTION跳转到对应的activity中,  通过在源码工程下全局搜索 然后找到对应的Activity, 我们发现是GrantPermissionsActivity.java

        <activity android:name="com.android.packageinstaller.permission.ui.GrantPermissionsActivity"android:configChanges="keyboardHidden|screenSize"android:excludeFromRecents="true"android:theme="@style/GrantPermissions"android:visibleToInstantApps="true"android:inheritShowWhenLocked="true"><intent-filter android:priority="1"><action android:name="android.content.pm.action.REQUEST_PERMISSIONS" /><category android:name="android.intent.category.DEFAULT" /></intent-filter></activity>

确定是唯一的,出现这个界面对话框时,我们也可以通过adb shell dumpsys window | grep mFocus

命令确定一下Activity找的是不是对的.

知识储备: 在Android(<=9)版本上, 动态申请权限的对话框是集成在 packages/apps/PackageInstaller 模块中, 在Android(>=10)版本上,是在packages/apps/PermissionController中,单独把这块拿出来了

3. 对话框事件处理是在GrantPermissionsViewHandlerImpl.java中,   允许,拒绝, 仅在使用该应用时允许  对应的代码如下:

    @Overridepublic void onClick(View view) {switch (view.getId()) {case R.id.permission_allow_button:if (mResultListener != null) {view.performAccessibilityAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);mResultListener.onPermissionGrantResult(mGroupName, GRANTED_ALWAYS);}break;case R.id.permission_allow_always_button:if (mResultListener != null) {view.performAccessibilityAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);mResultListener.onPermissionGrantResult(mGroupName, GRANTED_ALWAYS);}break;case R.id.permission_allow_foreground_only_button:if (mResultListener != null) {view.performAccessibilityAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);mResultListener.onPermissionGrantResult(mGroupName,GRANTED_FOREGROUND_ONLY);}break;case R.id.permission_deny_button:if (mResultListener != null) {view.performAccessibilityAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);mResultListener.onPermissionGrantResult(mGroupName, DENIED);}break;case R.id.permission_deny_and_dont_ask_again_button:if (mResultListener != null) {view.performAccessibilityAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);mResultListener.onPermissionGrantResult(mGroupName,DENIED_DO_NOT_ASK_AGAIN);}break;case R.id.permission_more_info_button:Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS);intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mAppPackageName);intent.putExtra(Intent.EXTRA_USER, mUserHandle);intent.putExtra(ManagePermissionsActivity.EXTRA_ALL_PERMISSIONS, true);mActivity.startActivity(intent);break;}}

3. 赋予应用默认运行时权限

        有些用户觉得app要申请权限比较麻烦,就有定制软件默认就赋予某个应用运行时权限,不弹出对话框,我们看看怎么修改呢?

   先来看frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java中的systemReady()方法

        // If we upgraded grant all default permissions before kicking off.for (int userId : grantPermissionsUserIds) {mDefaultPermissionPolicy.grantDefaultPermissions(userId);}

跳转到DefaultPermissionGrantPolicy.java中

    public void grantDefaultPermissions(int userId) {grantPermissionsToSysComponentsAndPrivApps(userId);//默认赋予应用的运行时权限grantDefaultSystemHandlerPermissions(userId);grantDefaultPermissionExceptions(userId);synchronized (mLock) {mDefaultPermissionsGrantedUsers.put(userId, userId);}}

 如下这些代码,就是默认赋予运行时权限的地方

 private void grantDefaultSystemHandlerPermissions(int userId) {..................// Downloads providergrantSystemFixedPermissionsToSystemPackage(getDefaultProviderAuthorityPackage("downloads", userId), userId,STORAGE_PERMISSIONS);// Downloads UIgrantSystemFixedPermissionsToSystemPackage(getDefaultSystemHandlerActivityPackage(DownloadManager.ACTION_VIEW_DOWNLOADS, userId),userId, STORAGE_PERMISSIONS);// Storage providergrantSystemFixedPermissionsToSystemPackage(getDefaultProviderAuthorityPackage("com.android.externalstorage.documents", userId),userId, STORAGE_PERMISSIONS);// CertInstallergrantSystemFixedPermissionsToSystemPackage(getDefaultSystemHandlerActivityPackage(Credentials.INSTALL_ACTION, userId), userId,STORAGE_PERMISSIONS);// Dialerif (dialerAppPackageNames == null) {String dialerPackage =getDefaultSystemHandlerActivityPackage(Intent.ACTION_DIAL, userId);grantDefaultPermissionsToDefaultSystemDialerApp(dialerPackage, userId);} else {for (String dialerAppPackageName : dialerAppPackageNames) {grantDefaultPermissionsToDefaultSystemDialerApp(dialerAppPackageName, userId);}}// Sim call managerif (simCallManagerPackageNames != null) {for (String simCallManagerPackageName : simCallManagerPackageNames) {grantDefaultPermissionsToDefaultSystemSimCallManager(simCallManagerPackageName, userId);}}// Use Open Wifiif (useOpenWifiAppPackageNames != null) {for (String useOpenWifiPackageName : useOpenWifiAppPackageNames) {grantDefaultPermissionsToDefaultSystemUseOpenWifiApp(useOpenWifiPackageName, userId);}}// 添加代码,赋予应用默认的运行时权限,不弹出申请对话框.grantPermissionsToSystemPackage("com.android.mytestapp", userId, STORAGE_PERMISSIONS);}

如果你想添加自己的应用默认赋予运行时权限的话,可以这样子修改,如下:

添加包名 和 运行时权限数组

grantPermissionsToSystemPackage("com.android.mytestapp", userId, STORAGE_PERMISSIONS);

http://www.dt0577.cn/news/33858.html

相关文章:

  • 申请关闭网站深圳网络推广网站推广
  • 西安免费做网站机构腾讯广告联盟
  • 做房产销售可以在哪些网站上找客户查询网 网站查询
  • java 做网站的书简阳seo排名优化课程
  • 建设厅建筑业信息网真假网站自己做网站的软件
  • asp.net网站开发介绍aso优化{ }贴吧
  • 发票 网站建设种子搜索神器
  • wordpress 小工具 修改上海专业的seo推广咨询电话
  • 网络营销专员岗位职责seo全网营销的方式
  • 做牙的网站叫什么网络推广的基本方法有哪些
  • 设计网站公司都选亿企邦百度搜索广告怎么投放
  • 深圳企业网站制作哪家好软文代写平台有哪些
  • 百度自助网站建设小学生抄写新闻20字
  • 网站建设怎么用长尾做标题seo外链技巧
  • 怎样做网站排名刷关键词的平台
  • 现在还用dw做网站设计么淘宝指数转换
  • 淄博做网站跟优化网络营销好找工作吗
  • 有没有如何做网站的书百度站长平台网站提交
  • 营销网站建设一薇网络推广怎么找客户
  • 做网站有哪些语言seo研究协会网是干什么的
  • 页面设计制作网站源码网站维护中
  • 北京住房和城乡建设部网站首页百度投放广告流程
  • 做游戏交易网站关键词排名优化技巧
  • pinterest的优点长沙官网seo收费标准
  • 淄博临淄网站建设优化大师有用吗
  • 外贸网站推企业网络推广平台
  • 在什么网站做推广最好北京cms建站模板
  • 什么不属于网站推广软件seo咨询师
  • 南宁网站推广费用下载百度浏览器
  • 南通城乡建设局网站初学者做电商怎么入手