Android 应用基础技术9_第1页
Android 应用基础技术9_第2页
Android 应用基础技术9_第3页
Android 应用基础技术9_第4页
Android 应用基础技术9_第5页
已阅读5页,还剩43页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第14章权限管理信息和数据安全管理是软件开发中的重要内容。Android通过权限管理达成信息/数据安全目标。从Android的6.0(API23)版本开始,到现今的Android16(API36),Android对权限管理做出了很大调整。为了处理不同Android版本之间的权限管理方式和要求不相容的问题,导致Android的权限管理是Android应用开发中的一个较为繁琐的事情。本章对Android权限管理进行梳理,以期在未来的编程实践中能够处理权限管理问题。目录14.1了解Android权限14.2普通权限申请及使用14.3重要权限申请及使用14.4课后同步练习14.5Android权限管理的本质和自定义权限14.6课后同步练习14.1了解Android权限回顾一下上一章从服务端获取图片并显示在APP程序上的例子,注意一下程序配置文件AndroidManifest.xml文件中的两句语句:它们都是向用户请求权限:在将应用程序安装到用户手机上时,Android安装程序会提示用户所安装的程序申请获取“查询网络状态”权限和“访问网络”权限。如果用户同意,那么,所安装的程序在运行时将能够查询网络状态,以及访问网络;如果用户不同意,那么,所安装的程序在运行时将不能够查询网络状态或者访问网络。<uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/><uses-permissionandroid:name="android.permission.INTERNET"/>因为“查询网络状态”权限和“访问网络”权限不会对用户系统/数据/信息造成不良影响,因此,它们属于“普通权限”:只需要在AndroidManifest.xml文件中声明即可。还有一类权限,称为“危险权限”或者称为“重要权限”。对于危险权限或者重要,应用程序不仅需要在AndroidManifest.xml文件中对所使用权限进行声明,还需要在运行时请求用户授予权限,只有用户许可,程序才可以访问相应数据或设备,否则,如果用户不同意,应用程序是不能访问权限所保护的相应数据或设备的。因为一旦用户授予程序相应权限,程序如果对权限使用不当,可能会对用户系统/数据/信息造成非常不良影响,这类权限称为“危险权限”。Android6.0是Android权限管理的一个分水岭。在Android6.0之前,所有权限都属于普通权限。在Android6.0及后续版本将权限划分为普通权限和重要权限。Android的普通权限和重要权限的划分不是绝对的。随着Android版本升级,某个原先属于普通权限的权限可能会被划分到重要权限中。这种分类的未来不确定性是导致Android权限管理复杂性因素之一。14.2普通权限申请及使用下面通过一个例子介绍如何申请和使用Android普通权限。android.permission.VIBRATE、android.permission.ACCESS_NETWORK_STATE是Android的普通权限,它们分别是在控制手机振动和获取网络状态时需要的权限。这个例子包含两个按钮,分别用于控制手机振动和获取网络状态功能。为此,新建名称为ch1401的工程。然后,修改主布局文件activity_main.xml为如下代码:<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="/apk/res/android"xmlns:app="/apk/res-auto"xmlns:tools="/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity">

<Buttonandroid:id="@+id/btn01"android:layout_width="match_parent"android:layout_height="64dp"android:layout_margin="5dp"android:text="振动手机4秒"/>

<Buttonandroid:id="@+id/btn02"android:layout_width="match_parent"android:layout_height="64dp"android:layout_margin="5dp"android:text="获取网络状态"/>

</LinearLayout>修改MainActivity.java。在编写响应按钮“振动手机4秒”的代码时,显示了如图所示的权限提示信息。点击箭头3所指向的功能操作项,显示如图所示的界面:将在AndroidManifest.xml文件中为应用程序增加振动手机权限,代码如下:<?xmlversion="1.0"encoding="utf-8"?><manifestxmlns:android="/apk/res/android"xmlns:tools="/tools">

<uses-permissionandroid:name="android.permission.VIBRATE"/>

<applicationandroid:allowBackup="true"android:dataExtractionRules="@xml/data_extraction_rules"android:fullBackupContent="@xml/backup_rules"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.Ch1401"><activityandroid:name=".MainActivity"android:exported="true"><intent-filter><actionandroid:name="ent.action.MAIN"/>

<categoryandroid:name="ent.category.LAUNCHER"/></intent-filter></activity></application>

</manifest>按照类似的方式,完成对第二个按钮“获取网络状态”按钮的处理。完整AndroidManifest.xml文件如下:<?xmlversion="1.0"encoding="utf-8"?><manifestxmlns:android="/apk/res/android"xmlns:tools="/tools">

<uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/><uses-permissionandroid:name="android.permission.VIBRATE"/>

<applicationandroid:allowBackup="true"android:dataExtractionRules="@xml/data_extraction_rules"android:fullBackupContent="@xml/backup_rules"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.Ch1401"><activityandroid:name=".MainActivity"android:exported="true"><intent-filter><actionandroid:name="ent.action.MAIN"/>

<categoryandroid:name="ent.category.LAUNCHER"/></intent-filter></activity></application>

</manifest>完整MainActivity.java代码如下:packagecom.example.ch1401;

importandroid.content.Context;import.ConnectivityManager;import.Network;import.NetworkCapabilities;importandroid.os.Bundle;importandroid.os.Vibrator;importandroid.view.View;importandroid.widget.Button;importandroid.widget.Toast;

importandroidx.activity.EdgeToEdge;importandroidx.appcompat.app.AppCompatActivity;importandroidx.core.graphics.Insets;importandroidx.core.view.ViewCompat;importandroidx.core.view.WindowInsetsCompat;

publicclassMainActivityextendsAppCompatActivityimplementsView.OnClickListener{

@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);EdgeToEdge.enable(this);setContentView(R.layout.activity_main);ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main),(v,insets)->{InsetssystemBars=insets.getInsets(WindowInsetsCompat.Type.systemBars());v.setPadding(systemBars.left,systemBars.top,systemBars.right,systemBars.bottom);returninsets;});

Buttonbtn01=findViewById(R.id.btn01);btn01.setOnClickListener(this);Buttonbtn02=findViewById(R.id.btn02);btn02.setOnClickListener(this);}

@OverridepublicvoidonClick(Viewv){intid=v.getId();if(id==R.id.btn01){Vibratorvibrator=(Vibrator)getSystemService(Context.VIBRATOR_SERVICE);//震动4000毫秒(秒)vibrator.vibrate(5000);}else{ConnectivityManagercm=(ConnectivityManager)this.getSystemService(MainActivity.CONNECTIVITY_SERVICE);Networknetwork=cm.getActiveNetwork();if(network==null){Toast.makeText(this,"unavailable",Toast.LENGTH_LONG).show();}else{Toast.makeText(this,"networkavailable",Toast.LENGTH_LONG).show();}}}}从这个例子也可以看出,在编程实践中,不要过于担心哪些操作需要申请权限,按照正常思路编写程序代码即可。对特殊的需要权限的操作,AndroidStudio开发工具会提醒编程者需要申请权限,然后按照AndroidStudio提示增加权限申请声明即可。特别是对于普通权限的申请和使用,在编程实践中使用起来是相对简单的,并且,对于普通权限,在所有的Android版本下处理方式都是相同的:在AndroidManifest.xml文件中声明,然后再程序中访问权限保护下的资源即可。14.3重要权限申请及使用对于重要权限,应用程序除了需要在AndroidManifest.xml文件中申明以外,还需要再程序运行时动态向用户申请。因此,对于重要权限的申请和使用,Android平台管理地相对严格。下面举例说明如何申请和使用Android重要权限。android.permission.POST_NOTIFICATIONS权限用于控制应用程序是否可以发通知,从Android13开始,它是Android重要权限。这个例子包含一个按钮,用于发送通知系统。为此,新建名称为ch1402的工程。在新建Android工程时,在“MinimumSDK”选项,Android已经默认选择Android7.0作为最低支持版本,如图。因为默认的版本大于6.0,因此,可以认为,所有的Android危险权限/重要权限都需要在运行时再次申请。完成创建工程后,修改主布局文件activity_main.xml为如下代码:<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="/apk/res/android"xmlns:app="/apk/res-auto"xmlns:tools="/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity">

<Buttonandroid:id="@+id/btn01"android:layout_width="match_parent"android:layout_height="64dp"android:layout_margin="5dp"android:text="发送通知"/>

</LinearLayout>在AndroidManifest.xml文件中增加声明发送通知的权限声明语句,如下:<uses-permissionandroid:name="android.permission.POST_NOTIFICATIONS"/>完整的MainActivity.java代码,如下:packagecom.example.ch1402;

importandroid.Manifest;importandroid.app.AlertDialog;importandroid.app.Notification;importandroid.app.NotificationChannel;importandroid.app.NotificationManager;importandroid.content.DialogInterface;importandroid.content.pm.PackageManager;importandroid.os.Build;importandroid.os.Bundle;importandroid.view.View;importandroid.widget.Button;

importandroidx.activity.EdgeToEdge;importandroidx.annotation.NonNull;importandroidx.appcompat.app.AppCompatActivity;importandroidx.core.graphics.Insets;importandroidx.core.view.ViewCompat;importandroidx.core.view.WindowInsetsCompat;

publicclassMainActivityextendsAppCompatActivityimplementsView.OnClickListener{

@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);EdgeToEdge.enable(this);setContentView(R.layout.activity_main);ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main),(v,insets)->{InsetssystemBars=insets.getInsets(WindowInsetsCompat.Type.systemBars());v.setPadding(systemBars.left,systemBars.top,systemBars.right,systemBars.bottom);returninsets;});

Buttonbtn01=findViewById(R.id.btn01);btn01.setOnClickListener(this);}

@OverridepublicvoidonClick(Viewv){intid=v.getId();if(id==R.id.btn01){sendNotification();}}

privatefinalintPOST_NOTIFICATIONS_REQUEST_CODE=1000;privatevoidsendNotification(){if(this.checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS)!=PackageManager.PERMISSION_GRANTED){if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.VANILLA_ICE_CREAM){if(this.shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)){this.requestPermissions(newString[]{Manifest.permission.POST_NOTIFICATIONS},POST_NOTIFICATIONS_REQUEST_CODE);}}else{this.requestPermissions(newString[]{Manifest.permission.READ_CONTACTS},POST_NOTIFICATIONS_REQUEST_CODE);}}else{doSendNotification();}}

privatevoiddoSendNotification(){NotificationManagernotificationManager=(NotificationManager)getSystemService(NOTIFICATION_SERVICE);CharSequencetext="学习发送通知,看看需要的总要权限";Notification.Builderbuilder=null;if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){builder=newNotification.Builder(this,"TEST");NotificationChannelchannel=null;channel=newNotificationChannel("TEST","学习发送通知",NotificationManager.IMPORTANCE_DEFAULT);notificationManager.createNotificationChannel(channel);

}else{builder=newNotification.Builder(this);}builder.setContentTitle(text);builder.setContentText(text+"...");builder.setSmallIcon(android.R.drawable.star_on);Notificationnotification=builder.build();notificationManager.notify((int)System.currentTimeMillis(),notification);}

@OverridepublicvoidonRequestPermissionsResult(intrequestCode,@NonNullString[]permissions,@NonNullint[]grantResults){super.onRequestPermissionsResult(requestCode,permissions,grantResults);if(requestCode==POST_NOTIFICATIONS_REQUEST_CODE){if(grantResults.length>0&&grantResults[0]==PackageManager.PERMISSION_GRANTED){doSendNotification();}else{alertDialog();}}}

privatevoidalertDialog(){finalAlertDialog.BuildernormalDialog=newAlertDialog.Builder(MainActivity.this);normalDialog.setIcon(android.R.drawable.ic_dialog_info);normalDialog.setTitle("授权失败");normalDialog.setMessage("你没有给程序授权,程序将不能发送通知");normalDialog.setPositiveButton("确定",newDialogInterface.OnClickListener(){@OverridepublicvoidonClick(DialogInterfacedialog,intwhich){}});normalDialog.show();}}14.4课后同步练习Android的权限管理是一项复杂的工作,应用程序为了使用Android的一些功能,需要申请Android权限。随着Android版本的更新和升级,权限管理的粒度和策略都可能发生变化。课后仔细阅读Android权限管理相关资料,整理一份较为完整的权限列表及各个权限所控制的资源目标。14.5Android自定义权限从上几节的关于Android权限及其使用的介绍可以了解到,Android的权限,无论是普通权限还是重要权限,本质上就是为保护数据/设备而设置的一道安全关口,只有得到了授权的程序才可以访问这些数据或者使用这些设备。因为Android平台中有许多数据/设备,不是任何程序都可以随意使用的,因此,每个这样的数据/设备都需要进行权限保护,这就可以解释为什么Android平台中存在如此众多的权限的原因。其实开发者也可以自定义自己的权限。现在假设某一个开发者有一些非常有价值的数据,这些数据非常有价值,以至于许多程序都想使用这些数据,怎么办?这个开发者可以为这些数据设置一个权限,对于其他的程序,只有得到授权的程序才可以使用和访问这些数据。也就是说,开发者可以自定义自己的为保护有价值数据的权限。下面举一个例子说明如何自定义权限,以及如何申请和使用自定义权限。因为涉及到一个程序要访问另一个程序的资源,所以,这个例子包括两个APP:APP1和APP2。在APP1中定义一个Activity,并为该Activity设置了访问权限,然后让APP2来访问APP1中的这个受到保护的Activity。首先新建一个名称为ch1403APP1的工程,修改其主布局文件activity_main.xml为如下代码:<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="/apk/res/android"xmlns:app="/apk/res-auto"xmlns:tools="/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity">

<Buttonandroid:id="@+id/btn01"android:layout_width="match_parent"android:layout_height="64dp"android:text="打开自己的第二个Activity"/>

</LinearLayout>为第二个Activity,也就是被权限保护的Activity创建布局文件,命名这个布局文件为second.xml,其代码如下:需要在mipmap资源目录下放置名称为a01.jpg的图片。<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent">

<ImageViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:scaleType="fitCenter"android:src="@mipmap/a01"/>

</LinearLayout>然后新建一个Activity,用于显示这个布局。命名这个Activity为SecondActivity.java,其代码如下:packagecom.example.ch1403app1;

importandroid.app.Activity;importandroid.os.Bundle;

importandroidx.annotation.Nullable;

publicclassSecondActivityextendsActivity{@OverrideprotectedvoidonCreate(@NullableBundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.second);}}修改MainActivity.java,当点击按钮“打开自己的第二个Activity”时,打开SecondActivity。修改后的MainActivity.java代码如下:packagecom.example.ch1403app1;

importandroid.content.Intent;importandroid.os.Bundle;importandroid.view.View;importandroid.widget.Button;

importandroidx.activity.EdgeToEdge;importandroidx.appcompat.app.AppCompatActivity;importandroidx.core.graphics.Insets;importandroidx.core.view.ViewCompat;importandroidx.core.view.WindowInsetsCompat;

publicclassMainActivityextendsAppCompatActivityimplementsView.OnClickListener{

@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);EdgeToEdge.enable(this);setContentView(R.layout.activity_main);ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main),(v,insets)->{InsetssystemBars=insets.getInsets(WindowInsetsCompat.Type.systemBars());v.setPadding(systemBars.left,systemBars.top,systemBars.right,systemBars.bottom);returninsets;});

Buttonbtn01=findViewById(R.id.btn01);btn01.setOnClickListener(this);}

@OverridepublicvoidonClick(Viewv){intid=v.getId();if(id==R.id.btn01){Intenti=newIntent("com.example.ch1403APP1.A1");i.addCategory(Intent.CATEGORY_DEFAULT);this.startActivity(i);}}}修改AndroidManifest.xml文件,在其中定义权限,并用自定义的权限保护SecondActivity的使用。修改后的AndroidManifest.xml文件如下:<?xmlversion="1.0"encoding="utf-8"?><manifestxmlns:android="/apk/res/android"xmlns:tools="/tools">

<permission-groupandroid:name="android.permission-group.COST_MONEY"android:label="@string/fortest2"android:description="@string/fortest2"/>

<permissionandroid:name="com.example.ch1403APP1.permission.SECOND_ACTIVITY"android:label="第二个Activity"android:description="@string/fortest"android:permissionGroup="android.permission-group.COST_MONEY"android:protectionLevel="normal"/>

<applicationandroid:allowBackup="true"android:dataExtractionRules="@xml/data_extraction_rules"android:fullBackupContent="@xml/backup_rules"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.Ch1403APP1"><activityandroid:name=".MainActivity"android:exported="true"><intent-filter><actionandroid:name="ent.action.MAIN"/><categoryandroid:name="ent.category.LAUNCHER"/></intent-filter></activity>

<activityandroid:name=".SecondActivity"android:exported="true"android:permission="com.example.ch1403APP1.permission.SECOND_ACTIVITY"><intent-filter><actionandroid:name="com.example.ch1403APP1.A1"/><categoryandroid:name="ent.category.DEFAULT"/></intent-filter></activity>

</application>

</manifest>还需要在strings.xml文件中添加需要的字符串定义:<resources><stringname="app_name">ch1403APP1</string>

<stringname="fortest">测试自定义权限</string><stringname="fortest2">测试自定义权限的权限组</string>

</resources>现在构建APP2访问APP1中受到保护的SecondActivity。为此,新建名称为ch1403APP2的工程,修改其主布局文件activity_main.xml为如下代码:<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="/apk/res/android"xmlns:app="/apk/res-auto"xmlns:tools="/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity">

<Buttonandroid:id="@+id/btn01"android:layout_width="match_parent"android:layout_height="64dp"android:text="打开APP1的SecondActivity"/>

</LinearLayout>修改MainActivity.java,处理按钮的点击事件,也就是要打开APP1的SecondActivity。修改后的MainActivity.java代码如下:packagecom.example.ch1403app2;

importandroid.content.Intent;importandroid.os.Bundle;importandroid.view.View;importandroid.widget.Button;

importandroidx.activity.EdgeToEdge;importandroidx.appcompat.app.AppCompatActivity;importandroidx.core.graphics.Insets;importandroidx.core.view.ViewCompat;importandroidx.core.view.WindowInsetsCompat;

publicclassMainActivityextendsAppCompatActivityimplementsView.OnClickListener{

@OverrideprotectedvoidonCreate(BundlesavedInstanc

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论