美文网首页
Android数据存储,运行时权限

Android数据存储,运行时权限

作者: 云承寒 | 来源:发表于2017-06-28 13:24 被阅读0次

    Android存储目录

    Android的底层支持是Linux,不同于Windows,没有分盘的概念,是以文件夹形式呈现,可以理解为一个应用就是一个用户。

    • data目录
      手机内部存储目录(手机本身内存)

    • mnt
      手机外部存储目录(SD卡)

    Android手机存储目录结构
    应用程序目录展开
    • /data/data目录
      开发的程序都存储在这个目录下。


      /data/data目录存储手机程序
    • /data/data/应用包名/cache目录
      一般用来缓存不重要的数据,保存图片。

    • /data/data/应用包名/databases目录
      一般用来存放数据库文件,SQLite。

    • /data/data/应用包名/files目录
      一般保存的是重要的信息,用户信息,应用配置。

    /data/data/包名/结构

    Android文件存储

    通过Environment类,获取目录。
    Environment提供的API都是静态的,可以直接.
    
    检测SDCard是否挂载:getExternalStorageState()
    获取SDCard目录:getExternalStorageDirectory()
    获取/data目录:getDataDirectory()
    获取下载/缓存内容目录:getDownloadCacheDirectory()
    
    private void demo() {
            File dataDirectory = Environment.getDataDirectory();
            File storageDirectory = Environment.getExternalStorageDirectory();
            File downloadCacheDirectory = Environment.getDownloadCacheDirectory();
    
            String state = Environment.getExternalStorageState();
            if (state.equals(Environment.MEDIA_MOUNTED)) {
                Log.i(TAG, "SDCard exists");
            }else{
                Log.i(TAG, "SDCard not exists");
            }
        }
    
    Context 提供的获取目录API
    获取/data/data/包名/cache目录:getCacheDir()
    获取/data/data/包名/files目录:getFilesDir()
    
     private void demo() {
         File filesDir = getFilesDir();
         File cacheDir = getCacheDir();
    }
    
    openFileOutput,openFileInput
    Activity 提供的API
    获取输入流:openFileOutput()
    获取输出流:openFileInput()
    
    FileOutputStream fops = openFileOutput(name, MODE_PRIVATE);
    参数
      1.指定文件名称,不能包含路径分隔符"/" 。
      2.文件权限
          只在本程序内读写:MODE_PRIVATE
          追加内容:MODE_APPEND 
          
    如果文件不存在,Android 会自动创建它。
    创建的文件保存在/data/data/<package name>/files目录。
    
    FileInputStream fips = openFileInput(path);
    
      private void demo() {
            try {
                FileOutputStream fos = openFileOutput("demo.txt", MODE_PRIVATE);
                FileInputStream fis = openFileInput("demo.txt");
    
                fos.write("write demo".getBytes());
                fos.flush();
    
                int len;
                byte[] buf = new byte[1024];
    
                while ((len = fis.read(buf)) != -1) {
                    Log.i(TAG, new String(buf, 0, len));
                }
    
                fis.close();
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    运行时权限

    Android 6.0 后将权限分为两类

    • 普通权限
      不会直接威胁到用户的隐私和安全,系统会自动帮我们授权。

    • 运行时权限
      能直接威胁到用户隐私安全的操作,需要运行时用户手动授权。

    Android危险权限
    
    CALENDAR(日历)
      READ_CALENDAR
      WRITE_CALENDAR
    
    CAMERA(相机)
      CAMERA
    
    CONTACTS(联系人)
      READ_CONTACTS
      WRITE_CONTACTS
      GET_ACCOUNTS
    
    LOCATION(位置)
      ACCESS_FINE_LOCATION
      ACCESS_COARSE_LOCATION
    
    MICROPHONE(麦克风)
      RECORD_AUDIO
    
    PHONE(手机)
      READ_PHONE_STATE
      CALL_PHONE
      ERAD_CALL_LOG
      WRITE_CALL_LOG
      ADD_VOICEMAIL
      USE_SIP
      PROCESS_OUTGOING_CALLS
    
    SENSORS(传感器)
      BODY_SENSORS
    
    SMS(短信)
      SEND_SMS
      RECEIVE_SMS
      READ_SMS
      RECEIVE_WAP_PUSH
      RECEIVE_MMS
    
    STORAGE(存储卡)
      READ_EXTERNAL_STORAGE
      WRITE_EXTERNAL_STORAGE
    
    通过读写SDCard,看程序运行时申请权限
    
    1.在AndroidManifest.xml声明权限
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    
    2.
    public class MainActivity extends AppCompatActivity {
    
        private static final String TAG = "MainActivity";
        private Context mContext;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            mContext = this;
            writeSdcard();
            getPermission();
        }
    
        private void getPermission() {
            //检查权限是否存在
            if (ContextCompat.checkSelfPermission(mContext,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    != PackageManager.PERMISSION_GRANTED) {
    
                //向用户申请授权
                ActivityCompat.requestPermissions(this, new String[]{
                        Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        Manifest.permission.READ_EXTERNAL_STORAGE
                }, 1);
    
            } else {
                writeSdcard();
            }
        }
    
        private void writeSdcard() {
    
            if (Environment.MEDIA_MOUNTED.equals(
                    Environment.getExternalStorageState())) {
    
                File extDir = Environment.getExternalStorageDirectory();
                File goalFile = new File(extDir, "writeSdcard.txt");
    
                try {
                    BufferedWriter bw = new BufferedWriter(new FileWriter(goalFile));
                    BufferedReader br = new LineNumberReader(new FileReader(goalFile));
    
                    bw.write("Write writeSdcard data");
                    bw.flush();
    
                    String len;
                    while ((len = br.readLine()) != null) {
                        Log.i(TAG, len);
                    }
    
                    br.close();
                    bw.close();
    
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                Log.i(TAG, "SDCard not exists");
            }
        }
    
        //用户授权完后回调
        @Override
        public void onRequestPermissionsResult(int requestCode,
                                               @NonNull String[] permissions,
                                               @NonNull int[] grantResults) {
            switch (requestCode) {
                case 1:
                    if (grantResults.length > 0 &&
                            grantResults[0] == PackageManager.PERMISSION_GRANTED)
                        writeSdcard();
                    else
                        Log.i(TAG, "not permission");
                    break;
            }
        }
    }
    

    SharedPreferences键值存储

    SharedPreferences是一种轻型的数据存储方式,本质是基于XML文件存储key-value键值对数据,通常用来存储一些简单的配置信息。

    获取SharedPreferences对象
    
    1.Context提供的方式
      getSharedPreferences("spName", MODE_PRIVATE);
    
    2.Activity提供的方式
      以当前类名作为 sp 的文件名
      getPreferences(MODE_PRIVATE);
    
    3.PreferenceManager提供的方式
      使用当前应用程序的包名作为前缀来命名sp
      PreferenceManager.getDefaultSharedPreferences(this);
    
     private void demo() {
            getSharedPreferences("spName", MODE_PRIVATE);
            getPreferences(MODE_PRIVATE);
            PreferenceManager.getDefaultSharedPreferences(this);
        }
    
    存储数据和获取数据
    private void demo() {
            SharedPreferences sp = getSharedPreferences("spDemo", MODE_PRIVATE);
            sp.edit().putString("key", "value").apply();
            String result = sp.getString("key", "default");
            Log.i(TAG, result);
    }
    

    SQLite存储

    Android内置数据库,支持标准的SQL语法,遵循ACID事务。

    SQLite支持的数据类型
    数据类型
    整型 Integer
    实数型 Real
    字符型 Text
    二进制 Blob
    空值 Null
    DDL
    1.Create table
    借助Android提供的抽象类SQLiteOpenHelper,可以建表和升级数据库。
    public class MyDataBaseHelper extends SQLiteOpenHelper {
    
        public static final String DB_NAME = "demo.db";
        public static final int DB_VERSION = 1;
    
        public static final String TABLE_NAME = "t_studen";
    
        public MyDataBaseHelper(Context context) {
            super(context, DB_NAME, null, DB_VERSION);
        }
    
        //当数据库文件创建时调用,可以在此方法创建多个数据库表
        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL("create table " + TABLE_NAME +
                    "(_id integer primary key autoincrement," +
                    "name text," +
                    "age real)");
        }
    
        //升级数据库,可以删除/添加/修改数据库表
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    
            //如果想升级表,比如添加一个字段,要先删除之前存在的表
            db.execSQL("drop table if exists " + TABLE_NAME);
            onCreate(db);
        }
    }
    
    
    
    2.Context也提供了一个方法来打开或创建数据库。
    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            SQLiteDatabase db = openOrCreateDatabase("demo.db", MODE_PRIVATE, null);
            db.execSQL("create table tt_student(" +
                    "_id integer primary key autoincrement," +
                    "name text," +
                    "age real)");
    }
    
    DML

    SQLiteOpenHelper中提供了两个实例方法,用来打开或创建一个数据库,并返回一个可以对数据库进行读写的对象(SQLiteDatabase)。

    1.getWritableDatabase()
    先尝试用读写的方式打开数据库,如果磁盘满了,将会报错。
    
    2.getReadableDatabase()
    直接以读写的方式打开数据库,如果磁盘满了,就用只读的方式打开数据库。
    
    public class MainActivity extends AppCompatActivity {
    
        private static final String TAG = "MainActivity";
    
        private MyDataBaseHelper mDbHelper;
        private SQLiteDatabase mSQLDb;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            loadDataBase();
            insertData();
            updateData();
            deleteData();
            queryData();
    
        }
    
        private void loadDataBase() {
            mDbHelper = new MyDataBaseHelper(this);
            mSQLDb = mDbHelper.getReadableDatabase();
        }
    
        private void insertData() {
            ContentValues cv = new ContentValues();
            cv.put("name", "张三");
            cv.put("age", 18);
            mSQLDb.insert(MyDataBaseHelper.TABLE_NAME, null, cv);
    
            cv.clear();
            cv.put("name", "李四");
            cv.put("age", 19);
            mSQLDb.insert(MyDataBaseHelper.TABLE_NAME, null, cv);
        }
    
        private void updateData() {
            ContentValues updateCv = new ContentValues();
            updateCv.put("name", "王五");
            mSQLDb.update(MyDataBaseHelper.TABLE_NAME,
                    updateCv,
                    "_id = ?",
                    new String[]{"2"});
        }
    
        private void deleteData() {
            mSQLDb.delete(MyDataBaseHelper.TABLE_NAME, "_id > ?", new String[]{"3"});
        }
    
        private void queryData() {
            Cursor cursor = mSQLDb.rawQuery("select * from " + 
                    MyDataBaseHelper.TABLE_NAME, 
                    null);
            
            String[] columnNames = cursor.getColumnNames();
            while (cursor.moveToNext()) {
                for (String item : columnNames) {
                    String name = cursor.getString(cursor.getColumnIndex(item));
                    Log.i(TAG, "queryData: " + name);
                }
            }
            cursor.close();
        }
    }
    
    数据库事务
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //打开或创建一个数据库 
            SQLiteDatabase db = openOrCreateDatabase("demo.db", MODE_PRIVATE, null);
            
            //开启事务
            db.beginTransaction();
            try {
    
                
                //没有异常就提交
                db.setTransactionSuccessful();
            } catch (Exception e) {
    
                
                //如果抛异常,就回滚
                db.endTransaction();
            }
        }
    

    相关文章

      网友评论

          本文标题:Android数据存储,运行时权限

          本文链接:https://www.haomeiwen.com/subject/zehucxtx.html