Android N 7 0 应用间共享文件(FileProvider)

分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

                       

Android N 之前的 Uri

常规Uri有两种:

  • 媒体文件的Uri是content://, 表示这是一个数据库数据。去数据库查询正常返回。
  • 其他的文件Uri是file://, 表示这个是一个文件。这个uri是通过Uri.fromFile(File file)方法生成。

Android N 之前,这些uri可以传递到其他应用。

Android N 中共享文件

Android N 系统,Android 框架执行的 StrictMode,API 禁止向您的应用外公开 file://URI
如果一项包含文件 URI 的 Intent 离开您的应用,应用会停止运行,并出现 FileUriExposedException异常。官方文档在Android 7.0 行为变更进行了详细说明

android.os.FileUriExposedException: file:///storage/emulated/0/Download/appName-2.3.0.apk exposed beyond app through Intent.getData()
  
  
  • 1
  • 2

若要在应用间共享文件,您应发送一项 content://URI(代替file://URI),并授予 URI 临时访问权限。

FileProvider这个类就是把一个文件File,转换为 content://URI的

FileProviderContentProvider子类,所以FileProvider的使用方法,和ContentProvider使用基本上是一样的

如何共享文件,简单5步:

1、在AndroidManifest.xml中<application>标签下声明一个provider

<provider    android:name="android.support.v4.content.FileProvider"    android:authorities="app的包名.fileProvider"    android:grantUriPermissions="true"    android:exported="false">    <meta-data        android:name="android.support.FILE_PROVIDER_PATHS"        android:resource="@xml/file_paths" /></provider>
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

注意: 
authorities:app的包名.fileProvider
grantUriPermissions:必须是true,表示授予 URI 临时访问权限 ( readPermission, writePermission, and permission attributes)
exportedtrue: The provider is available to other applications. false: The provider is not available to other applications. 
resource:自定义的xml文件(下面会介绍)

2、在res目录下新建一个xml文件夹,并且新建一个file_paths的xml文件(如下图)

这里写图片描述

3、打开file_paths.xml文件,添加指定的分享目录:

file_paths.xml 是这样的

<?xml version="1.0" encoding="utf-8"?><paths xmlns:android="http://schemas.android.com/apk/res/android">    <root-path name="root" path="" />    <files-path name="files" path="" />    <cache-path name="cache" path="" />    <external-path name="external" path="" />    <external-files-path name="name" path="path" />     <external-cache-path name="name" path="path" /></paths>
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在paths节点内部支持以下几个子节点,分别为:

<root-path/> 代表设备的根目录new File(“/”);
<files-path/>代表: Context.getFilesDir()
<external-path/>代表: Environment.getExternalStorageDirectory()
<cache-path/>代表: getCacheDir()
<external-files-path>代表context.getExternalFilesDirs()
<external-cache-path>代表getExternalCacheDirs()

每个节点都支持两个属性:

name:给这个访问路径起个名字
path:需要临时授权访问的相对路径(.代表所有路径)

<external-path        name="external"        path="pics" />
  
  
  • 1
  • 2
  • 3

path即为代表external-path目录下的子目录,目录为:Environment.getExternalStorageDirectory()/pics,其他同理。

现在要使用content://uri替代file://uri,那么,content://的uri如何定义呢?总不能使用文件路径吧,那不是骗自己么~

所以,需要一个虚拟的路径对文件路径进行映射,所以需要编写个xml文件,通过path以及xml节点确定可访问的目录,通过name属性来映射真实的文件路径。

<?xml version="1.0" encoding="utf-8"?><paths xmlns:android="http://schemas.android.com/apk/res/android">    <!--代表外部存储区域的根目录下的文件 Environment.getExternalStorageDirectory()/DCIM/camerademo目录-->    <external-path name="DCIM" path="DCIM/camerademo" />    <!--代表外部存储区域的根目录下的文件 Environment.getExternalStorageDirectory()/目录-->    <external-path path="." name="external_storage_root" />    <!--代表外部存储区域的根目录下的文件 Environment.getExternalStorageDirectory()/Pictures/camerademo目录-->    <external-path name="Pictures" path="Pictures/camerademo" />    <!--代表app 私有的存储区域 Context.getFilesDir()目录下的images目录 /data/user/0/com.hm.camerademo/files/images-->    <files-path name="private_files" path="images" />    <!--代表app 私有的存储区域 Context.getCacheDir()目录下的images目录 /data/user/0/com.hm.camerademo/cache/images-->    <cache-path name="private_cache" path="images" />    <!--代表app 外部存储区域根目录下的文件 Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)目录下的Pictures目录-->    <!--/storage/emulated/0/Android/data/com.xx.xxxxxx/files/Pictures-->    <external-files-path name="external_files" path="Pictures" />    <!--代表app 外部存储区域根目录下的文件 Context.getExternalCacheDir目录下的images目录-->    <!--/storage/emulated/0/Android/data/com.xx.xxxxxx/cache/images-->    <external-cache-path name="external_cache" path="" /></paths>
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

下面的例子使用SDCard,代码如下:

<?xml version="1.0" encoding="utf-8"?><paths xmlns:android="http://schemas.android.com/apk/res/android">    <external-path name="external" path="" /></paths>
  
  
  • 1
  • 2
  • 3
  • 4

4、FileProvider API的使用

/**     * 打开相机拍照     *     * @param activity     * @return     */    public static void openCamera(Activity activity) {        String filename = new SimpleDateFormat("yyyyMMdd-HHmmss", Locale.CHINA)                    .format(new Date()) + ".png";        File pictureFile = new File(Environment.getExternalStorageDirectory(), filename );        Intent mIntent = new Intent();        mIntent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {            Uri contentUri = FileProvider.getUriForFile(activity, "app的包名.fileProvider", pictureFile );            //拍照结果输出到这个uri对应的file中            mIntent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);            //对这个uri进行授权            //mIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);            //对这个uri进行授权            mIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);        } else {            //拍照结果输出到这个uri对应的file中            mIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(pictureFile ));        }        mIntent.putExtra(MediaStore.Images.Media.ORIENTATION, 0);        activity.startActivityForResult(mIntent, REQUEST_CAMERA_IMAGE);    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

核心代码就这一行了~

Uri contentUri = FileProvider.getUriForFile(activity, "app的包名.fileProvider", pictureFile );
  
  
  • 1
  • 第二个参数就是我们配置的authorities,这个很正常了,总得映射到确定的ContentProvider吧~所以需要这个参数。

  • 第三个参数是指定的文件File

生成的uri:

content://com.xuexuan.fileprovider/external/20171201-094017.png
  
  
  • 1

可以看到格式为:content://authorities/paths中name的值/文件的相对路径,即name隐藏了可存储的文件夹路径。

这里需要多说一点,Uri 的最终路径,与file和path有很大关系

如果file的路径完全包含path路径的,则显示path路径+文件的相对路径,如下:

path路径 <external-path name="my_external" path="customscamera" />

file路径 /storage/emulated/0/customscamera/1534305129374.jpg

则 Uri 为:content://com.xuexuan.fileprovider/my_external/customscamera/1534305129374.jpg

如果file的路径不完全包含path路径的,则显示文件的绝对路径,如下:

path路径 <external-path name="my_external" path="123" />

file路径 /storage/emulated/0/customscamera/1534305129374.jpg

则 Uri 为:content://com.futureway.blealarm.fileProvider/profile_photo/storage/emulated/0/customscamera/1534305129374.jpg

5、对URI进行授权

上面代码有一行注释是:对这个uri进行授权。

授权有两种方式:

  1. Intent.addFlags,该方式主要用于针对intent.setData,setDataAndType以及setClipData相关方式传递uri的。
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
  
  
  • 1

2、使用函数进行授权和移除权限

  • grantUriPermission(String toPackage, Uri uri, 
    int modeFlags)函数来进行授权

  • revokeUriPermission(Uri uri, int modeFlags);移除权限

方式二较为麻烦,因为需要指定目标应用包名,很多时候并不清楚,所以需要通过PackageManager进行查找到所有匹配的应用,全部进行授权。不过更为稳妥~

List<ResolveInfo> resInfoList = context.getPackageManager()            .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);for (ResolveInfo resolveInfo : resInfoList) {    String packageName = resolveInfo.activityInfo.packageName;    context.grantUriPermission(packageName, uri, flag);}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

如果没有授权,可能会遇到这样的错误

java.lang.SecurityException: Permission Denial: opening provider android.support.v4.content.FileProvider         from ProcessRecord{18570a 27107:com.google.android.packageinstaller/u0a26} (pid=27107, uid=10026) that is not exported from UID 10004
  
  
  • 1
  • 2
  • 3

以下这两个问题,可参考这篇文章

  • 为什么在Android 7 设备上,Intent的action为ACTION_IMAGE_CAPTURE,不进行授权,不会遇到Permission Denial的问题

  • 为什么Android 4.4设备遇到权限问题,不通过addFlags这种方式解决

错误分析

报错

java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/DCIM/camerademo/20170226_110056248725175.jpg
  
  
  • 1

分析

在生成Uri 的时候,指定的文件所在的路径没有包含在path所指定的路径中

疑惑

遇到这样一个到现在没有理解的问题,在小米6,MIUI 9.0 上面,使用下面的代码,进行图片的裁剪。

1、如果不使用下面的函数授权,就会出现java.lang.SecurityException: Permission Denial的错误

2、使用了下面的函数授权,可以正常返回。但是返回的数据是null。但是在指定路径有裁剪后的照片输出。

有大神知道问题的原因,帮忙在评论里指导我一下,十分感谢

     /***     * 裁剪图片     * @param activity Activity     * @param uri 图片的Uri     */    public static void cropPicture(Activity activity, Uri uri) {        Intent intent = new Intent("com.android.camera.action.CROP");        intent.putExtra("crop", "true");// 才能出剪辑的小方框,不然没有剪辑功能,只能选取图片        intent.putExtra("aspectX", 1); // 放大缩小比例的X        intent.putExtra("aspectY", 1);// 放大缩小比例的X   这里的比例为:   1:1        intent.putExtra("outputX", 120);  //这个是限制输出图片大小        intent.putExtra("outputY", 120);        intent.putExtra("return-data", false);        //切图大小不足输出,无黑框        intent.putExtra("scale", true);        intent.putExtra("scaleUpIfNeeded", true);        Log.e("FaceUtil", "图片path:" + uri.toString());        File imageFile = new File(uri.getPath());        //输出图片的路径        File outputImageFile = new File(Environment.getExternalStorageDirectory(),                "picture" + System.currentTimeMillis() / 1000 + ".jpg");        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);            intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);            Uri contentUri = FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + ".fileProvider", imageFile);            Uri outputUri = FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + ".fileProvider", outputImageFile);            intent.setDataAndType(contentUri, "image/*");            //使用函数授权,所有的包名            List<ResolveInfo> resInfoList = activity.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);            for (ResolveInfo resolveInfo : resInfoList) {                String packageName = resolveInfo.activityInfo.packageName;                activity.grantUriPermission(packageName, outputUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);            }            //裁剪后的图片,将被保存在这个uri中            intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri);        } else {            //裁剪后的图片,将被保存在这个uri中            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(outputImageFile));            intent.setDataAndType(uri, "image/*");        }        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());        activity.startActivityForResult(intent, REQUEST_CROP_IMAGE);    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

参考:

Android 7.0 行为变更 通过FileProvider在应用间共享文件吧

https://developer.android.com/guide/topics/manifest/provider-element.html

Android7.0须知–应用间共享文件(FileProvider)

解决 Android N 7.0 上 报错:android.os.FileUriExposedException

FileProvider无法获取外置SD卡问题解决方案 | Failed to find configured root that contains

FileProvider 的使用(Failed to find configured root that contains/storage/emulated/0/DCIM/ )

Android中Uri和Path之间的转换

           

分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

package com.example.tigongzhe; import android.R.integer; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; import android.net.Uri; import android.provider.SyncStateContract.Helpers; import android.text.Selection; import android.util.Log; public class provider extends ContentProvider { private MyOpenHelper myOpenHelper; private SQLiteDatabase sqLiteDatabase; private static final UriMatcher URI_MATCHER=new UriMatcher(UriMatcher.NO_MATCH); private final String TAG="provider"; private static final String authority="com.example.tigongzhe.provider"; static { URI_MATCHER.addURI(authority, "contacter", 1); URI_MATCHER.addURI(authority, "contacter/#", 2); } private static final String _id="id"; private static final String name="name"; private static final String num="num"; @Override public boolean onCreate() { // TODO Auto-generated method stub myOpenHelper=new MyOpenHelper(getContext(), DB_Name, null, version_1); return true; } @Override public String getType(Uri uri) { // TODO Auto-generated method stub int flag=URI_MATCHER.match(uri); switch (flag) { case 2: return "vnd.android.cursor.item/contacter"; case 1: return "vnd.android.dir.item/contacter"; default: throw new IllegalArgumentException("异常参数"); } } @Override public Uri insert(Uri uri, ContentValues values) { // TODO Auto-generated method stub sqLiteDatabase=myOpenHelper.getWritableDatabase(); int flag=URI_MATCHER.match(uri); switch (flag) { case 1: sqLiteDatabase.insert(Table_Name, name, values); break; case 2: long id=sqLiteDatabase.insert(Table_Name, name, values); ContentUris.withAppendedId(uri, id); default: break; } return uri; } @Override public Cursor query(Uri uri, String[] arg1, String arg2, String[] arg3, String arg4) { // TODO Auto-generated method stub Cursor cursor; sqLiteDatabase=myOpenHelper.getReadableDatabase(); int flag=URI_MATCHER.match(uri); switch (flag) { case 1: cursor=sqLiteDatabase.query(Table_Name, arg1, arg2, arg3, null, null,arg4); break; case 2: long id=ContentUris.parseId(uri); arg2=(arg2==null||"".equals(arg2.trim()))? _id+"="+id:arg2+"and"+_id+"="+id; cursor=sqLiteDatabase.query(Table_Name, arg1, arg2, arg3, null, null,arg4); default: throw new IllegalArgumentException("参数错误"); } return cursor; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // TODO Auto-generated method stub int num=0; sqLiteDatabase=myOpenHelper.getWritableDatabase(); int flag=URI_MATCHER.match(uri); switch (flag) { case 1: num=sqLiteDatabase.update(Table_Name, values,selection, selectionArgs); break; case 2: long id=ContentUris.parseId(uri); selection=(selection==null||"".equals(selection.trim()))? _id+"="+id:selection+"and"+_id+"="+id; num=sqLiteDatabase.update(Table_Name, values,selection, selectionArgs); default: break; } return num; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // TODO Auto-generated method stub int num=0; sqLiteDatabase=myOpenHelper.getWritableDatabase(); int flag=URI_MATCHER.match(uri); switch (flag) { case 1: num=sqLiteDatabase.delete(Table_Name, selection, selectionArgs); break; case 2: long id=ContentUris.parseId(uri); selection=(selection==null||"".equals(selection.trim()))?_id+"="+id:selection+"and"+_id+"="+id; num=sqLiteDatabase.delete(Table_Name, selection, selectionArgs); default: throw new IllegalArgumentException("异常参数"); } return num; } private final String DB_Name = "mydb.db"; private final String Table_Name="contacter"; private final int version_1=1; private class MyOpenHelper extends SQLiteOpenHelper { public MyOpenHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); } /** * @description 当数据表无连接时创建新的表 */ @Override public void onCreate(SQLiteDatabase db) { String sql = " create table if not exists " + Table_Name + "(id INTEGER PRIMARY KEY AUTOINCREMENT," + "name varchar(64),num varchar(64))"; db.execSQL(sql); } /** * @description 当版本更新时触发的方法 */ @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { String sql = " drop table if exists " + Table_Name; db.execSQL(sql); onCreate(db); } } } +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.tigongzhe" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="18" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.example.tigongzhe.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <provider android:name=".provider" android:authorities="com.example.tigongzhe.provider" android:multiprocess="true" android:exported="true" android:permission="com.example.tigongzhe.permission" ></provider> </application> <permission android:name="com.example.tigongzhe.permission" android:protectionLevel="normal"></permission> </manifest> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++package com.example.tigongzhe; import android.R.integer; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; import android.net.Uri; import android.provider.SyncStateContract.Helpers; import android.text.Selection; import android.util.Log; public class provider extends ContentProvider { private MyOpenHelper myOpenHelper; private SQLiteDatabase sqLiteDatabase; private static final UriMatcher URI_MATCHER=new UriMatcher(UriMatcher.NO_MATCH); private final String TAG="provider"; private static final String authority="com.example.tigongzhe.provider"; static { URI_MATCHER.addURI(authority, "contacter", 1); URI_MATCHER.addURI(authority, "contacter/#", 2); } private static final String _id="id"; private static final String name="name"; private static final String num="num"; @Override public boolean onCreate() { // TODO Auto-generated method stub myOpenHelper=new MyOpenHelper(getContext(), DB_Name, null, version_1); return true; } @Override public String getType(Uri uri) { // TODO Auto-generated method stub int flag=URI_MATCHER.match(uri); switch (flag) { case 2: return "vnd.android.cursor.item/contacter"; case 1: return "vnd.android.dir.item/contacter"; default: throw new IllegalArgumentException("异常参数"); } } @Override public Uri insert(Uri uri, ContentValues values) { // TODO Auto-generated method stub sqLiteDatabase=myOpenHelper.getWritableDatabase(); int flag=URI_MATCHER.match(uri); switch (flag) { case 1: sqLiteDatabase.insert(Table_Name, name, values); break; case 2: long id=sqLiteDatabase.insert(Table_Name, name, values); ContentUris.withAppendedId(uri, id); default: break; } return uri; } @Override public Cursor query(Uri uri, String[] arg1, String arg2, String[] arg3, String arg4) { // TODO Auto-generated method stub Cursor cursor; sqLiteDatabase=myOpenHelper.getReadableDatabase(); int flag=URI_MATCHER.match(uri); switch (flag) { case 1: cursor=sqLiteDatabase.query(Table_Name, arg1, arg2, arg3, null, null,arg4); break; case 2: long id=ContentUris.parseId(uri); arg2=(arg2==null||"".equals(arg2.trim()))? _id+"="+id:arg2+"and"+_id+"="+id; cursor=sqLiteDatabase.query(Table_Name, arg1, arg2, arg3, null, null,arg4); default: throw new IllegalArgumentException("参数错误"); } return cursor; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // TODO Auto-generated method stub int num=0; sqLiteDatabase=myOpenHelper.getWritableDatabase(); int flag=URI_MATCHER.match(uri); switch (flag) { case 1: num=sqLiteDatabase.update(Table_Name, values,selection, selectionArgs); break; case 2: long id=ContentUris.parseId(uri); selection=(selection==null||"".equals(selection.trim()))? _id+"="+id:selection+"and"+_id+"="+id; num=sqLiteDatabase.update(Table_Name, values,selection, selectionArgs); default: break; } return num; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // TODO Auto-generated method stub int num=0; sqLiteDatabase=myOpenHelper.getWritableDatabase(); int flag=URI_MATCHER.match(uri); switch (flag) { case 1: num=sqLiteDatabase.delete(Table_Name, selection, selectionArgs); break; case 2: long id=ContentUris.parseId(uri); selection=(selection==null||"".equals(selection.trim()))?_id+"="+id:selection+"and"+_id+"="+id; num=sqLiteDatabase.delete(Table_Name, selection, selectionArgs); default: throw new IllegalArgumentException("异常参数"); } return num; } private final String DB_Name = "mydb.db"; private final String Table_Name="contacter"; private final int version_1=1; private class MyOpenHelper extends SQLiteOpenHelper { public MyOpenHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); } /** * @description 当数据表无连接时创建新的表 */ @Override public void onCreate(SQLiteDatabase db) { String sql = " create table if not exists " + Table_Name + "(id INTEGER PRIMARY KEY AUTOINCREMENT," + "name varchar(64),num varchar(64))"; db.execSQL(sql); } /** * @description 当版本更新时触发的方法 */ @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { String sql = " drop table if exists " + Table_Name; db.execSQL(sql); onCreate(db); } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值