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

陵水黎族自治县网站建设_网站建设公司_建站流程_seo优化

自己怎样用手机建网站,做秩序册的网站,2016响应式网站模版,建设监理协会网站文章目录普通权限与危险权限运行时申请权限内容提供器运用安卓封装好的内容提供器自实现的内容提供器概念实现普通权限与危险权限 主要用于不同应用程序之间在保证被访数据的安全性的基础上#xff0c;实现数据共享的功能。 在 Android 6.0 开始引入了运行时权限的功能… 文章目录普通权限与危险权限运行时申请权限内容提供器运用安卓封装好的内容提供器自实现的内容提供器概念实现普通权限与危险权限 主要用于不同应用程序之间在保证被访数据的安全性的基础上实现数据共享的功能。 在 Android 6.0 开始引入了运行时权限的功能用户在安装软件时不需要一次性授权所有的权限而是在软件的使用过程中再对某一项权限进行申请。Android 将权限分为两类 普通权限 不会直接影响到用户的安全和隐私的权限对于这部分权限系统自动授权。危险权限 可能会涉及到用户的隐私或者对设备安全性造成影响的权限。 危险权限如下这些权限需要进行运行时权限处理不在表中的权限只需要在 AndroidManifest.xml 添加权限声明即可 表中的每一个危险权限都属于一个权限组虽然在进行权限处理的时候使用的是权限名但是一旦用户同意授权那么该权限名对应的权限组中的所有权限也会同时被授权。 运行时申请权限 给按钮注册点击事件 Button button1 findViewById(R.id.button_1);button1.setOnClickListener((View view)-{try {/*// 打开拨号界面无需声明权限Intent intent new Intent(Intent.ACTION_DIAL);*/// 打电话需要生命权限Intent intent new Intent(Intent.ACTION_CALL);intent.setData(Uri.parse(tel:15309276440));startActivity(intent);} catch (SecurityException e){e.printStackTrace();}});在注册表中加入 这样的程序在 Android 6.0 之前都可以正常运行但是在更高的版本点击按钮后没有任何效果错误信息如下 权限被禁止。 修复这个问题申请运行时权限的流程 将打电话的行为封装成函数 call() private void call(){try {/*// 打开拨号界面无需声明权限Intent intent new Intent(Intent.ACTION_DIAL);*/// 打电话需要声明权限Intent intent new Intent(Intent.ACTION_CALL);intent.setData(Uri.parse(tel:15309276440));startActivity(intent);} catch (SecurityException e){e.printStackTrace();}}修改 onCreate 方法内的点击按钮行为 Button button1 findViewById(R.id.button_1);button1.setOnClickListener((View view)-{// 相等说明用户已授权不等说明未授权if(ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE)! PackageManager.PERMISSION_GRANTED){// 申请授权ActivityCompat.requestPermissions(this,new String[] { Manifest.permission.CALL_PHONE}, 1);} else {call();}});通过 ContextCompat.checkSelfPermission() 方法检测用户是否已授权该方法有两个参数 context具体权限名 未授权则需要调用 ActivityCompat.requestPermissions() 方法来向用户申请授权该方法接受三个参数 Activity 实例也就是当前活动。String 数组也就是要申请的权限名。请求码必须唯一这里传入 1。 调用 requestPermissions 方法后系统会弹出一个权限申请的对话框用户可以选择同意或拒绝权限申请不论同意与否都会回调 onRequestPermissionsResult 方法该方法有三个参数 唯一的请求码存储被申请权限名的 String 数组授权结果 grantResults // 权限申请对话框点击结果回调Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {switch (requestCode) {case 1:if (grantResults.length 0 grantResults[0] PackageManager.PERMISSION_GRANTED) {call();} else {Toast.makeText(this, 用户拒绝授权, Toast.LENGTH_LONG).show();}break;default:}if(!ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.CALL_PHONE)){AlertDialog.Builder dialog new AlertDialog.Builder(this);dialog.setTitle(电话权限不可用).setMessage(请在-应用设置-权限中允许APP使用电话权限。);dialog.setCancelable(false);dialog.setPositiveButton(立即设置, (dialog1, which) - goToAppSetting());dialog.setNegativeButton(取消, (dialog2, which) - dialog2.dismiss());dialog.show();}}shouldShowRequestPermissionRationale 方法的返回值 应用第一次安装并且权限被禁用时返回 true权限第一次被禁用时返回 true权限被禁用且不再提示时返回 false已授权时返回 false 总结该方法返回值表示需不需要向用户解释一下你的 app 为什么需要这个权限。当用户已经授权或者用户明确禁止权限被禁用且不再提示的时候就不需要再去解释了所以此时会返回 false。 权限不可用时引导用户手动启用权限 // 跳转到权限设置界面private void goToAppSetting() {Intent intent new Intent();intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);Uri uri Uri.fromParts(package, getPackageName(), null);intent.setData(uri);startActivity(intent);}上述代码的运行逻辑是 通过 checkSelfPermission 检验用户是否已授权 已授权则直接调用 call 打电话未授权则通过 requestPermissions 申请授权 第一次申请授权被拒绝点击按钮仍会二次调用 requestPermissions此时 shouldShowRequestPermissionRationale 返回值为 true第二次申请授权被拒绝权限被视为禁止使用调用 requestPermissions 不会再弹出询问弹窗但是仍会回调 onRequestPermissionsResult此时 shouldShowRequestPermissionRationale 返回值为 false因此会弹出对话框询问用户是否要跳转到设置界面开启权限用户可以通过 “立即设置” 跳转到 setting界面 来开放权限此后再点击按钮会因为已授权而不再调用 requestPermissions 。 点击按钮的运行结果 点击 DENY 内容提供器 内容提供器有两种已有的如 Android 系统自带的电话簿、短信等程序提供的供其他程序访问部分内部数据的外部访问接口、自实现的。 ContentResolver类 是内容提供器的具体类可以通过 Context类 中的 getContentResolver()方法 获取该类的实例该类提供了一系列的 CRUD 操作这些增删改查方法都使用 Uri参数 替代 表名参数。内容URI 主要由三部分组成 content 协议声明authority 用于区分不同应用程序一般采用程序包名命名path 用区分同一程序中不同表。 举个例子 内容URI 只是一串字符还需通过 Uri.parse() 方法解析成 Uri对象 才可做为参数。 关于内容提供器的增删查改方法这里仅解释较为复杂的 query() 方法 查询完后返回一个 Cursor对象可以通过遍历其所有行来得到每一行数据。 运用安卓封装好的内容提供器 运用联系人应用的内容提供器读取联系人信息并在 ListView 中显示。 声明权限 布局文件 contacts_layout.xml LinearLayoutxmlns:androidhttp://schemas.android.com/apk/res/androidandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentListViewandroid:idid/contacts_viewandroid:layout_widthmatch_parentandroid:layout_heightmatch_parent/ /LinearLayout活动文件 ContactsActivity public class ContactsActivity extends AppCompatActivity {ArrayAdapterString adapter;ListString contactsList new ArrayList();Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.contacts_layout);ListView contactsView findViewById(R.id.contacts_view);adapter new ArrayAdapter(this, android.R.layout.simple_list_item_1, contactsList);contactsView.setAdapter(adapter);if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)! PackageManager.PERMISSION_GRANTED){ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.READ_CONTACTS}, 1);}else {readContacts();}}private void readContacts() {Cursor cursor null;try {Uri uri ContactsContract.CommonDataKinds.Phone.CONTENT_URI;cursor getContentResolver().query(uri, null, null,null, null, null);if(cursor ! null){while(cursor.moveToNext()){// 获取联系人姓名String name cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));// 获取联系人手机号String number cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));contactsList.add(name \n number);}// 刷新ListViewadapter.notifyDataSetChanged();// 关闭 Cursor 对象cursor.close();}} catch (Exception e) {e.printStackTrace();} finally {// 和上面的关闭二选一/*if(cursor ! null){cursor.close();}*/}}Overridepublic void onRequestPermissionsResult(int requestCode, NonNull String[] permissions,NonNull int[] grantResults) {switch (requestCode){case 1:if(grantResults.length 0 grantResults[0] PackageManager.PERMISSION_GRANTED){readContacts();}else {Toast.makeText(this, 用户拒绝授权, Toast.LENGTH_LONG).show();}break;}} }运行结果 自实现的内容提供器 概念 可以通过新建一个 ContentProvider子类 的方式来创建自己的内容提供器。ContentProvider类 有 6 个抽象方法需要我们重写onCreate()、query()、insert()、update()、delete()、getType()。这里重点介绍 onCreate 和 getType 两个方法 onCreate() 当 ContentProvider 尝试访问程序中数据时初始化内容提供器通常在这里完成对数据库的创建和升级等操作。返回 true 表内容提供器初始化成功false 表失败。getType() 根据传入的 内容URI 来返回相应的 MIME 类型。MIME字符串 主要由三部分组成 必须要以 vnd 开头如果 内容URI 以 路径 结尾则后接 android.cursor.dir/如果以 id 结尾则后接 android.cursor.item/最后接上 vnd.authority.path 内容URI 的格式主要有两种 以路径结尾表示期望访问表中所有数据 content://com.example.app.provider/table 访问 table 表中所有数据以 id 结尾表示期望访问表中拥有相应 id 的数据content://com.example.app.provider/table/1 访问 table 表中 id 为 1 的数据 还可以使用通配符 匹配任意表content://com.example.app.provider/*匹配 table 表中任意一行数据content://com.example.app.provider/table/# 内容URI 对应的 MIME类型 content://com.example.app.provider/table vnd.android.cursor.dir/vnd.com.example.app.provider.tablecontent://com.example.app.provider/table/1 vnd.android.cursor.item/vnd.com.example.app.provider.table 如何匹配 内容URI 呢 首先借助 UriMatcher.addURI() 方法将 内容URI的相关信息 添加进匹配器中相关信息对应方法的三个参数authority、path、(int)code。前两者之前讲过这里不再赘述code 用以唯一标识要访问的资源。 再借助 UriMatcher.match() 方法传入一个 Uri对象 通过返回的 code 来匹配对应的操作。 如何保证隐私数据不泄露 因为所有的 CRUD操作 都需要匹配到相应的 内容URI 格式才能进行只要不向 UriMatcher 中添加 隐私数据的URI 就好。 实现 那现在开始自实现内容提供器操作的数据库是该篇博客中的例子 在 AndroidManifest.xml 文件中注册 自定义的内容提供器 MyContentProvider public class MyContentProvider extends ContentProvider {public static final int STUDENT_DIR 0;public static final int STUDENT_ITEM 1;public static final int CLASS_DIR 2;public static final int CLASS_ITEM 3;public static final String AUTHORITY com.example.activitytest.CustomType.provider;private static UriMatcher uriMatcher;private MyDatabaseHelper dbHelper;static {uriMatcher new UriMatcher(UriMatcher.NO_MATCH);uriMatcher.addURI(AUTHORITY, student, STUDENT_DIR);uriMatcher.addURI(AUTHORITY, student/#, STUDENT_ITEM);uriMatcher.addURI(AUTHORITY, class, CLASS_DIR);uriMatcher.addURI(AUTHORITY, class/#, CLASS_ITEM);}Overridepublic int delete(Uri uri, String selection, String[] selectionArgs) {SQLiteDatabase db dbHelper.getWritableDatabase();int deleteRows 0;switch (uriMatcher.match(uri)){case STUDENT_DIR:deleteRows db.delete(Student, selection, selectionArgs);break;case STUDENT_ITEM:String studentId uri.getPathSegments().get(1);deleteRows db.delete(Student, id ?, new String[]{studentId});break;case CLASS_DIR:deleteRows db.delete(Class, selection, selectionArgs);break;case CLASS_ITEM:String classId uri.getPathSegments().get(1);deleteRows db.delete(Class,id ?, new String[]{classId});break;}return deleteRows;}Overridepublic String getType(Uri uri) {switch (uriMatcher.match(uri)){case STUDENT_DIR:return vnd.android.cursor.dir/vnd.com.example.activitytest.CustomType.provider.student;case STUDENT_ITEM:return vnd.android.cursor.item/vnd.com.example.activitytest.CustomType.provider.student;case CLASS_DIR:return vnd.android.cursor.dir/vnd.com.example.activitytest.CustomType.provider.class;case CLASS_ITEM:return vnd.android.cursor.item/vnd.com.example.activitytest.CustomType.provider.class;}return null;}Overridepublic Uri insert(Uri uri, ContentValues values) {SQLiteDatabase db dbHelper.getWritableDatabase();Uri uriReturn null;switch (uriMatcher.match(uri)){case STUDENT_DIR:case STUDENT_ITEM:long studentId db.insert(Student, null, values);uriReturn Uri.parse(content:// AUTHORITY /student/ studentId);break;case CLASS_DIR:case CLASS_ITEM:long classId db.insert(Class, null, values);uriReturn Uri.parse(content:// AUTHORITY /class/ classId);break;default:break;}return uriReturn;}Overridepublic boolean onCreate() {dbHelper new MyDatabaseHelper(getContext(), Student.db, null, 4);return true;}Overridepublic Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,String sortOrder) {SQLiteDatabase db dbHelper.getReadableDatabase();Cursor cursor null;switch (uriMatcher.match(uri)){case STUDENT_DIR:cursor db.query(Student, projection, selection, selectionArgs,null, null, sortOrder);break;case STUDENT_ITEM:// Uri字符串中以 “/” 作为分割0部分是路径1部分则是id。即获取Uri字符串中的id部分。String studentId uri.getPathSegments().get(1);cursor db.query(Student, projection, id ?, new String[]{ studentId }, null, null, sortOrder);break;case CLASS_DIR:cursor db.query(Class, projection, selection, selectionArgs,null, null, sortOrder);break;case CLASS_ITEM:String classId uri.getPathSegments().get(1);cursor db.query(Class, projection, id ?, new String[]{ classId }, null, null, sortOrder);break;default:break;}return cursor;}Overridepublic int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {SQLiteDatabase db dbHelper.getWritableDatabase();int updateRows 0;switch (uriMatcher.match(uri)){case STUDENT_DIR:updateRows db.update(Student, values, selection, selectionArgs);break;case STUDENT_ITEM:String studentId uri.getPathSegments().get(1);updateRows db.update(Student, values, id ?, new String[]{studentId});break;case CLASS_DIR:updateRows db.update(Class, values, selection, selectionArgs);break;case CLASS_ITEM:String classId uri.getPathSegments().get(1);updateRows db.update(Class, values, id ?, new String[]{classId});break;default:break;}return updateRows;} }onCreate() 初始化一个 MyDatabaseHelper 实例返回 true 表示内容提供器初始化成功。 query() 通过 MyDatabaseHelper 获取 SQLiteDatabase 实例通过 uriMatcher.match(uri) 分析用户想访问的表通过 SQLiteDatabase.query() 进行查询并返回 Cursor 对象 访问单条数据时调用 uri.getPathSegments() 将 内容URI 权限之后的部分以 “/” 作为分割并将结果放入一个字符串列表列表的第0个位置是路径第1个位置则是id。 insert() 前两步同 query() 通过 SQLiteDatabase.insert() 进行添加但由于该方法要求返回一个 Uri对象因此需要调用 Uri.parse() 将 URI字符串 解析成 Uri对象。 接下来新建一个程序用来调用上面的内容提供器 public class MainActivity extends AppCompatActivity {private static final String TAG MainActivity;private String newId;public static final String AUTHORITY content://com.example.activitytest.CustomType.provider/;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button button_add findViewById(R.id.button_add);button_add.setOnClickListener(v-{Uri uri Uri.parse(AUTHORITY student/);ContentValues values new ContentValues();values.put(name, zj);values.put(age, 21);values.put(weight, 90);values.put(gender, girl);Uri insertUri getContentResolver().insert(uri, values);newId insertUri.getPathSegments().get(1);Log.e(TAG, 咕咕insertUri.toString());});Button button_query findViewById(R.id.button_query);button_query.setOnClickListener(v-{Uri uri Uri.parse(AUTHORITY student);Cursor cursor getContentResolver().query(uri, null, null,null, null);while(cursor.moveToNext()){String name cursor.getString(cursor.getColumnIndex(name));int age cursor.getInt(cursor.getColumnIndex(age));double weight cursor.getDouble(cursor.getColumnIndex(weight));String gender cursor.getString(cursor.getColumnIndex(gender));String res name age weight gender;Toast.makeText(this, res, Toast.LENGTH_LONG).show();}cursor.close();Log.e(TAG, 表中数据显示完毕);});Button button_update findViewById(R.id.button_update);button_update.setOnClickListener(v-{Uri uri Uri.parse(AUTHORITY student/ newId);ContentValues values new ContentValues();values.put(name, cjl);values.put(weight, 95);getContentResolver().update(uri, values, null, null);});Button button_delete findViewById(R.id.button_delete);button_delete.setOnClickListener(v-{if(newId!null newId.compareTo(0) 0){Uri uri Uri.parse(AUTHORITY student/ newId);getContentResolver().delete(uri, null, null);newId String.valueOf(Integer.valueOf(newId)-1);Log.e(TAG, 最后一个id newId);}else{Toast.makeText(this, 表中已经没有数据了, Toast.LENGTH_LONG).show();}});} }如果模拟器是 Android 11那么该程序的清单文件需要加上 queries 标签原因见本博客
http://www.lebaoying.cn/news/84873.html

相关文章:

  • 中国建设银行 网站登录南宁seo排名外包
  • 市桥做网站中国芗城区城乡建设局网站
  • 婚恋网站排名前10肥东建设网站
  • wordpress 站点错误整站seo
  • 陕西省建设集团公司网站做粉丝网站会侵权吗
  • 网站建设用什么网站好一点wordpress是做什么的
  • 网站开发网页前置开发wordpress搜索条件
  • 苏州做网站哪家比较好可以做围棋题的网站
  • 货架 网站建设 牛商网网站式登录页面模板下载地址
  • 郑州网站关键词排名技术代理百度推广代理赚钱
  • 网站建设完成后怎么上传服务器黑龙江做网站
  • 培训推广 seo排名优化百度
  • 网站建设 移动端wordpress页面生成二维码
  • wordpress 3.9 wpmuseo tdk
  • 如何在国外网站做翻译兼职WordPress怎么给网页效果
  • 烟台外贸网站建设公司北京网站制作人才
  • 网站传不上图片企业网站的建设目的包含什么
  • 怎么做微信领券网站网站建设模块培训ppt
  • 外贸网站搭建难不难新泰高品质网站建设
  • 深圳企业专业网站设计自己家里做网站网速慢
  • 东莞市官网网站建设公司快对小程序入口
  • 各地民营企业创新前行深圳seo优化外包公司
  • 专业建站推广网络公司杭州公司网站制作
  • 网站视频管理系统青岛君哲网站建设公司怎么样
  • 网站开发进度设计网站项目计划说明书
  • 滨州市住房和城乡建设厅网站wordpress 分类菜单高亮
  • 中国企业网站开发热点新闻
  • 宁波网站建设rswl360浏览器网页版
  • 织梦系统做的网站忘记登录密码东莞网页设计教程
  • 网站推广公司经理职责电子商务网站开发课程设计论文