4.数据持久化->SharedPreference 内部空间 外部空间

安卓手机只能读写在/data/data  或者sdcard中

SharedPreference

四大组件之学习contentProvider之前要学习数据持久化->SharedPreference

SharedPreference轻量级数据存储,一般存储app设置的一些信息,例如用户设置的一些是否自动推送等功能

xml文件 K-V形式

SharedPreferences             对文件"读"的操作

SharedPreferences.Editor   对文件"写"的操作

我们通过这种形式存储的文件全部存储在这个路径下:

/data/data/<applicationId>/shared_prefs   要root权限才能打开

 

例子:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/text1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="输入内容"/>

    <Button
        android:id="@+id/storeBtn"
        android:text="保存"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <Button
        android:id="@+id/showBtn"
        android:text="显示"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <TextView
        android:id="@+id/TextView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text=""/>

</LinearLayout>
package com.example.datasave1;

import androidx.appcompat.app.AppCompatActivity;

import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    Button storeBtn;
    Button showBtn;
    EditText editText;
    TextView textView;
    SharedPreferences msharedPreferences;
    SharedPreferences.Editor meditor;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        storeBtn = findViewById(R.id.storeBtn);
        showBtn = findViewById(R.id.showBtn);
        textView = findViewById(R.id.TextView1);
        editText = findViewById(R.id.text1);

        //第一个参数是文件名,第二个参数是文件的操作模式
        msharedPreferences = getSharedPreferences("data",MODE_PRIVATE);
        meditor = msharedPreferences.edit();

        //存储
        storeBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                meditor.putString("namehhh",editText.getText().toString());
                meditor.apply();
            }
        });

        //显示
        showBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
          //取的时候值缺省就行了 textView.setText(msharedPreferences.getString(
"namehhh","")); } }); } }

 Android存储概念

Android存储有内部存储和外部存储(公有目录  私有目录(随应用卸载而被删除))

内部存储:随应用卸载被删除

/data/data/<applicationId>/shared_prefs

/data/data/<applicationId>/databases

/data/data/<applicationId>/files

/data/data/<applicationId>/cache

外部存储:

  公有目录:Environment.getExternalStoragePublicDirectory(int type)

  私有目录:/mnt/sdcard/Android/data/data/<application>/cache

          /mnt/sdcard/Android/data/data/<application>/files

File 内部存储

FileOutputStream FileInputStream

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ImageView
            android:id="@+id/img"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:paddingTop="50dp"
            android:src="@drawable/ic_baseline_ac_unit_24"/>
        <TextView
            android:text="QQ"
            android:paddingTop="37dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="50dp"
            android:layout_toRightOf="@+id/img"/>

        <EditText
            android:id="@+id/edit1"
            android:layout_width="250dp"
            android:layout_height="wrap_content"
            android:hint="QQ号码"
            android:textSize="20dp"
            android:padding="30dp"
            android:inputType="number"
            android:layout_below="@+id/img"/>

        <EditText
            android:id="@+id/edit2"
            android:layout_width="250dp"
            android:layout_height="wrap_content"
            android:hint="密码"
            android:textSize="20dp"
            android:padding="30dp"
            android:inputType="textPassword"
            android:layout_below="@+id/edit1"/>

        <Button
            android:id="@+id/loginBtn"
            android:layout_width="250dp"
            android:layout_height="wrap_content"
            android:layout_below="@+id/edit2"
            android:text="保存数据"/>

        <Button
            android:id="@+id/showBtn"
            android:layout_marginTop="50dp"
            android:layout_width="250dp"
            android:layout_height="wrap_content"
            android:layout_below="@+id/loginBtn"
            android:text="显示数据"
            tools:ignore="OnClick" />

        <TextView
            android:id="@+id/showText"
            android:paddingTop="37dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="50dp"
            android:layout_below="@+id/showBtn"/>

    </RelativeLayout>
    
</LinearLayout>

 

 

 

 

package com.example.qqlogindemo;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;

/*
* 为什么我们直接写一个文件名的时候,去写文件,报出的异常是read——only
* 其实呢,在Android系统中,每一个应用呢就是一个用户,每个用户它的权限是特定的,不可操作其他应用的内容
* 以“/”为根目录,它跟windows不一样
* */

public class MainActivity extends AppCompatActivity {

    EditText account;
    EditText password;
    Button button;
    TextView showText;
    Button showBtn;
    File file;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //第一步找到控件
        initView();
        //设置点击事件
        initListener();
        //回显数据
        showAccountAndPassword();
    }

    //第一步找到控件
    private void initView(){
        account = findViewById(R.id.edit1);
        password = findViewById(R.id.edit2);
        button = findViewById(R.id.loginBtn);
        showBtn = findViewById(R.id.showBtn);
        showText = findViewById(R.id.showText);
    }

    //设置点击事件  处理登录事件
    private void initListener(){
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //拿到账号和密码
                String accountNum = String.valueOf(account.getText());
                String myPassword = String.valueOf(password.getText());
                //判空 以及提示用户
                if (TextUtils.isEmpty(accountNum) || TextUtils.isEmpty(myPassword)){
                    Toast.makeText(getApplicationContext(),"账号或密码输入为空",Toast.LENGTH_SHORT).show();
                }else {
                    //保存账号和密码
                    saveAccountAndPawword(accountNum,myPassword);
                }
            }
        });
    }

    //保存账号和密码
    void saveAccountAndPawword(String accountNum,String myPassword){

        try {
            //在SD卡下新建一个文件夹
            //在Android开发时,一般我们使用以下代码获取储存路径.
            //"/data/data/com.example.qqlogindemo"当前app路径咋获取?? this.getFilesDir()
            //getFilesDir拿到的路径是 /data/user/0/com.example.qqlogindemo/files
            //获取缓存文件的路径  getCacheDir()
            Log.e("getFilesDir******", String.valueOf(this.getFilesDir()));
            File dir = new File(this.getFilesDir(),"bagabaga");
            if (!dir.exists()){
                dir.mkdirs();
            }
        //创建文件
            file = new File(dir,"hello.txt");
            if (!file.exists()){
                file.createNewFile();
            }
            FileOutputStream fos = new FileOutputStream(file);
            //以特定的格式存储
            fos.write((accountNum+"***"+myPassword).getBytes());
            Toast.makeText(getApplicationContext(),"数据保存成功",Toast.LENGTH_SHORT).show();
            Log.e("TAG****: ","保存用户信息");
            //fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //显示已保存的账号密码
    void showAccountAndPassword(){
        showBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    //输入流
                    FileInputStream ips = new FileInputStream(file.getPath());
                    Log.e("file.getPath()*****",file.getPath());
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(ips));
                    //读一行
                    String line = bufferedReader.readLine();
                    //fos.write((accountNum+"***"+myPassword).getBytes());
                    //上面这行代码是我们之前保存的数据形式,也就是说,我们拿到数据以后要对数据进行切割
                    String[] split = line.split("\\*\\*\\*");
                    String account = split[0];
                    String password = split[1];
                    Toast.makeText(getApplicationContext(),"账号是: "+account+"密码是: "+password,Toast.LENGTH_SHORT).show();
                    showText.setText("账号是: "+account+"密码是: "+password);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

 

File 外部存储(SD卡)

 

package com.example.qqlogindemo;

import static com.google.android.material.internal.ContextUtils.getActivity;

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class SDCardDemoActivity extends AppCompatActivity {

    Button loginBtn1;
    EditText edit3;

    //不光要在AndroidMainfest.xml中申请权限还要在这动态申请权限
    //**************************动态申请权限*************************************************
    private static final int REQUEST_EXTERNAL_STORAGE = 1;
    private static String[] PERMISSIONS_STORAGE = {
            "android.permission.READ_EXTERNAL_STORAGE",
            "android.permission.WRITE_EXTERNAL_STORAGE" };

    //************************动态申请权限的方法 写完之后直接在onCreate方法中直接使用就行了*********
    public static void verifyStoragePermissions(Activity activity) {

        try {
            //检测是否有写的权限
            int permission = ActivityCompat.checkSelfPermission(activity,
                    "android.permission.WRITE_EXTERNAL_STORAGE");
            if (permission != PackageManager.PERMISSION_GRANTED) {
                // 没有写的权限,去申请写的权限,会弹出对话框
                ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sdcard_demo);

        loginBtn1 = findViewById(R.id.loginBtn1);
        edit3 = findViewById(R.id.edit3);

        verifyStoragePermissions(this);

        loginBtn1.setOnClickListener(new View.OnClickListener() {
            @SuppressLint("NewApi")
            @RequiresApi(api = Build.VERSION_CODES.M)
            @Override
            public void onClick(View view) {
                //要在AndroidMainfest.xml的application标签头顶上中赋予读写权限
                //<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
                //<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
                File filePath = new File("/sdcard");
                File file = new File(filePath, "hello.txt");
                try {
                    if (!file.exists()) {
                        //创建文件
                        file.createNewFile();
                    }
                    FileOutputStream fos = new FileOutputStream(file);
                    //以特定形式存储数据
                    String s = edit3.getText().toString();
                    fos.write(s.getBytes());
                    fos.close();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });

    }
}

 

 

不同的手机厂商以及车载平台的sd卡文件夹名不一样,那我们咋整?

File filePath = new File(String.valueOf(Environment.getExternalStorageDirectory()));

判断SD卡是否挂载
if (Environment.getExternalStorageState().equals(
                        Environment.MEDIA_MOUNTED)) {
                     // sd card 可用
                    Log.e("sd是否挂载?: ","可用!");

                }else {
                    // 当前不可用
                    Log.e("sd是否挂载?: ","不可用!");
                }

 

获取SD卡剩余空间

//获取SD卡路径
        File path = Environment.getExternalStorageDirectory();
        //获取外部存储空间的所有信息
        StatFs stat = new StatFs(path.getPath());
        long blockSize;
        long totalBlocks;
        long availableBlocks;
        blockSize = stat.getBlockSize();            //获取空间块大小
        totalBlocks = stat.getBlockCount();    //获取空间块数量
        availableBlocks = stat.getAvailableBlocks();  //获取可用空间

 




posted @ 2021-09-13 15:02  涂妖教  阅读(102)  评论(0)    收藏  举报