安卓开发-基础知识补习3

听说点赞关注的人,身体健康,万事如意,工作顺利,爱情甜蜜,一夜暴富,升职加薪……最终迎娶白富美!!!

微信公众号:炜煜gzs

题目:安卓开发-基础知识补习3

内容简介:本文通过学习安卓零基础开发到入门的书籍,介绍了安卓的两种数据存储的方式,一种是内部存储空间文件的存取,另一种是SD卡空间的文件的存取。通过简单的介绍实现了不同方式的功能实现,使用java代码进行开发,如果有问题的地方请不吝指教,如果对文内内容有不理解的地方,也希望能积极主动的联系博主进行深刻的探讨,以便于更好的让博主记住这篇博文的内容,好让博主在发光发热的道路上越走越远。[手动狗头]努力,奋斗!

标题一:安卓中的数据存储

安卓中数据存储的方式大致分为以下五种

  1. 文件存储:安卓提供了openFileOutput()和openFileInput()方法读取设备上的文件,本是上是以java的I/O流方式读取数据,文件存储的关键是获取相应的输入流和输出流。
  2. SharedPreferces:是安卓提供的用来存储简单配置信息的一种方式,它采用键值对的形式以XML格式将数据存储到设备中。通常使用SharedPeferences存储一些应用该程序的配置信息,如用户名,密码等。
  3. SQLite数据库:SQLite是安卓自带的一个轻量级的数据库,它没有后台进程,整个数据库对应于一个文件。安卓为访问SQLite数据库提供了大量的边界的API,并且支持基本SQL语法,一般使用它作为负责数据的存储引擎,把相对复杂的结构化数据存储在本地。
  4. ContentProvider(内容提供者):安卓的四大组件之一,用于在应用程序之间进行数据交换的标准API。
  5. 网络数据读取:通过网络向服务器发送请求,获取相应数据或者将数据存储到服务器上。

内部存储控件文件的存取

​ 内部存储是指将数据以文件的形式存储到应用程序中。对于安卓应用来说,内部存储的数据属于应用程序的私有数据,如果其他应用程序想要操作本应用程序的文件,需要获取权限。当应用写在之后,内部存储的数据也就清空了,为了保证内存数据的安全,不让用户直接定位访问,安卓中对内部存储控件中文件的读取进行封装,用户不需要知道具体的存储路径就可以打开相应的文件输入/输出流。在Context类中提供了两个方法来打开I/O流。

FileInputStream openFi了Input(String name):获取应用程序中名为name的文件的对应的文件输入流。

FileOutputStream openFileOutput(String name,int node):获取应用程序名为name的文件对应的文件输出流。

name参数表示读取或者存入指定文件的文件名,不能包含路径分隔符“\”,如果文件不存在安卓胡i自动创建该文件。mode参数用于指定操作模式,Context类中定义了四种操作模式常量,如下

  1. Context.MODE_PRIVATE :为默认操作模式,代表该文件是私有的,只能被应用本身访问,在该模式下写入的内容会被覆盖原文件的内容。

  2. Context.MODE_APPEND:附加模式,会检查文件是否存在,存在就往文件后追加内容,否则创建新文件再写入新内容。

  3. Context.MODE_WORLD_READABLE:表示当i请安文件可以被其他应用读取。

  4. Context.MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入。

    提示:如果希望文件技能被其他应用读也能写,可以传入:Context.MODE_WORLD_READABLE+Context.MODE_WORLD_READABLE或者直接传入数值3,四种模式中除了APPEND模式会将内容追加到文件末尾,其他模式都会覆盖掉源文件的内容。

高版本安卓中建议采用更好的机制,例如通过ContentProvider暴露访问接口,或者通过服务广播,已经废弃了两个读写

在手机上创建文件和像文件中追加内容的步骤如下:

  1. 调用openFileOutput()方法传入文件的名称和操作的模式,该方法将会返回一个文件输出流。
  2. 调用文件输出流的write()方法,像文件写入内容。
  3. 调用文件输出流的close()方法,关闭文件输出流。

读取手机上文件的一般步骤如下:

  1. 调用openFileInput()方法传入读取数据的文件名,该方法返回一个文件输入流对象。
  2. 调用文件输入流对象的read()方法读取文件的内容。
  3. 调用文件输入流对象的close()方法关闭文件输入流。

布局文件如下:

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/edit_content"
            android:hint="请输入内容:"></EditText>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/btn_save"
            android:text="保存到手机内部存储空间"></Button>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/tv_content"
            android:lines="3"
            android:text="读取的内容:"
            android:textSize="15dp"></TextView>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/btn_read"
            android:text="读取文件"></Button>
    </LinearLayout>

java代码如下

    private EditText editText;
    private TextView textView;
    private Button buttonSave;
    private Button buttonRead;
    private String fileName="content.txt";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }
    private void initView() {
        editText = findViewById(R.id.edit_content);
        textView = findViewById(R.id.tv_content);
        buttonRead = findViewById(R.id.btn_read);
        buttonSave = findViewById(R.id.btn_save);
        buttonSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String content = editText.getText().toString();

                try {
                    FileOutputStream fos  = openFileOutput(fileName,MODE_PRIVATE);
                    fos.write(content.getBytes(StandardCharsets.UTF_8));
                    fos.close();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
        buttonRead.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    FileInputStream fis = openFileInput(fileName);
                    byte[] bytes = new byte[fis.available()];
                    fis.read(bytes);
                    String content = new String(bytes);
                    //textView.setText(content);
                    textView.setText("nihaohifdsajf");
                    fis.close();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

读取SD卡上的文件

内存中存放文件会直接影响软件的运行效率。因为SD卡的可移动性,可能被移除或者丢失,并且不是所有的手机都有SD卡,还有可能SD卡损坏或者安装不正确等。在访问之前需要验证手机端的SD卡状态,安卓提供了Envionment类完成这一操作,当外部设备可用并且具有读写权限是,就可以通过FileInputStream和FileOutputStream对象来读写外部设备中的文件。

SD卡中的数据涉及用户的隐私,访问是需要盛情相关的权限,需要使用到运行权限,即在程序运行时,提示用户进行给授权,因此,读写SD卡上的文件的主要步骤如下:

  1. 掉哦那个Ecvioronment的getExternalStorageState()方法判断手机是否存在SD卡,并且SD卡是否正常读写。Environment.getExternalStorageState()方法用于获取SD卡的状态,如果手机装有SD卡,并且可以进行读写,那么方法返回的状态等于Environment.MEDIA_MOUNTED
  2. 判断用户是否授权,如果没有授权,请求授权,如果授权了则下一步。
  3. 调用Enciroment的getExternalStorageDirectory()方法来获取外部存储器的目录,也就是SD卡的目录(如果知道SD卡目录,可以使用绝对路径表示,但不提倡,因为不同版本可能路径不同。)
  4. 使用FileInputStream或者FileOutputStream等读写SD卡文件。

提示:为了保证引用程序的安全性,安卓系统规定访问系统的一些关键信息时,必须申请权限,否则程序运行时会因为没有访问系统信息的权限而直接奔溃。根据程序适配的安卓SDK版本的不同,申请权限分为静态申请权限和动态申请权限两种方式。

  • 静态申请权限
    1. 静态申请权限的方式使用与安卓SDK6.0以下的版本。该方式是在清单文件(AndroidManifest.xml)的结点中声明需要申请的权限。以申请SD卡的读权限为例:

      <user-permission android:name="android.permission.READ_EXTERANAL_STORAGE"></user-permission>
      
  • 动态申请权限
    1. 当程序适配的安卓SDK为6.0及以上时,安卓改变了权限的管理模式,权限被分为正常权限和危险权限,具体如下

      • 正常权限:表示不会直接给用户隐私带来风险的权限,如请求网络的权限。

      • 危险权限:表示涉及用户隐私的权限,申请了该权限的应用可能涉及用户隐私信息的数据或资源,也可能对用户存储的数据或者其他应用的操作产生影响。危险权限一共有九组,分别为:

        1. 位置(LOCATION)、日历(CALENDAR)、照相机(CAMERA)、联系人(CONTACTS)、存储卡(STORAGE)、传感器(SENSORS)、麦克风(MICROPHONE)、电话(PHONE)、短信(SMS)。
      • 申请正常权限时使用静态申请权限的方式即可,但是对于一些涉及用户隐私的危险的权限,需要用户的授权才可以使用给,因此危险全年不仅需要在清单文件(AndroidManifest.xml)的结点中添加权限,还需要再代码中动态申请权限,以动态申请SD卡的读权限为例:

        ActivityCompat.requestPermissions(MainActivity.this,new String[] {Mainifest.permission.READ_EXTERNAL_STORAGE},1);
        

        requestPermissions()方法中包含3个参数,第一个参数为Context上下文,第二个参数为需要申请的权限,第三个参数为请求码。添加完动态申请权限后,运行程序,界面上会弹出是否允许申请权限的对话框,由用户进行授权。

      布局文件同上,java代码如下:

          private EditText editText;
          private TextView textView;
          private Button buttonSave;
          private Button buttonRead;
          private String fileName="content.txt";
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              initView();
          }
      
          @Override
          public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
              super.onRequestPermissionsResult(requestCode, permissions, grantResults);
              if (requestCode == 1){
                  for (int i = 0; i < permissions.length; i++) {
                      if (permissions[i].equals("android.permission.READ_EXTERNAL_STORAGE") &&
                          grantResults[i] == PackageManager.PERMISSION_GRANTED){
                          Toast.makeText(this,"授权成功",Toast.LENGTH_LONG).show();
                      }else {
                          Toast.makeText(this,"获取授权失败,请稍后再试!", Toast.LENGTH_LONG).show();
                      }
                  }
              }
          }
      
          private void initView() {
              editText = findViewById(R.id.edit_content);
              textView = findViewById(R.id.tv_content);
              buttonRead = findViewById(R.id.btn_read);
              buttonSave = findViewById(R.id.btn_save);
      
              buttonSave.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
                      String content = editText.getText().toString();
      
                      try {
                          FileOutputStream fos  = openFileOutput(fileName,MODE_PRIVATE);
                          fos.write(content.getBytes(StandardCharsets.UTF_8));
                          fos.close();
                      } catch (FileNotFoundException e) {
                          e.printStackTrace();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
              });
      
              buttonRead.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
                      try {
                          FileInputStream fis = openFileInput(fileName);
                          byte[] bytes = new byte[fis.available()];
                          fis.read(bytes);
                          String content = new String(bytes);
                          //textView.setText(content);
                          textView.setText("nihaohifdsajf");
                          fis.close();
                      } catch (FileNotFoundException e) {
                          e.printStackTrace();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
              });
      
      

    此处说明一点,在安卓8.0的环境下可以完美运行,能够正常保存读取文件,但是高版本安卓13就不能正常流畅的运行,只能保存,但是读取就会出错。

    SharedPreferences保存用户名和密码

  1. 这个类主要可以通过保存一个xml文件到安卓内存中,可以实现简单的登录等操作。保证了运行的流程性。

MainActivity.java代码

package com.example.administrator.chart0704;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.util.Map;

public class MainActivity extends AppCompatActivity {
    private TextView tvRegister;
    private TextView tvFindPwd;
    private EditText editName;
    private EditText editPwd;
    private Button btnLogin;
    private String userName;
    private String psw;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initListener();
        Map<String, String> uerInfo = SPSaveInfo.getInfoFromSP(this);
        if (uerInfo != null) {
            editName.setText(uerInfo.get("userName"));
            editPwd.setText(uerInfo.get("userPwd"));
        }
    }

    private void initView() {
        tvRegister = (TextView) findViewById(R.id.tv_register);
        editName = (EditText) findViewById(R.id.et_user_name);
        editPwd = (EditText) findViewById(R.id.et_psw);
        tvRegister = (TextView) findViewById(R.id.tv_register);
        tvFindPwd = (TextView) findViewById(R.id.tv_find_psw);
        btnLogin = (Button) findViewById(R.id.btn_login);
    }

    private void initListener() {
        btnLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                userName = editName.getText().toString().trim();
                psw = editPwd.getText().toString();
                if (userName.isEmpty() || psw.isEmpty()) {
                    Toast.makeText(MainActivity.this, "用户名或密码不能为空", Toast.LENGTH_SHORT).show();
                    return;
                } else {
                    Toast.makeText(MainActivity.this, "登录成功", Toast.LENGTH_SHORT).show();
                    boolean isSave = SPSaveInfo.saveInfoToSP(MainActivity.this, userName, psw);
                    if (isSave) {
                        Toast.makeText(MainActivity.this, "保存成功", Toast.LENGTH_SHORT).show();
                    }
                }
            }
        });
    }
}

MainActivityLayout.xml文件

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

    <ImageView
        android:id="@+id/iv_head"
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="70dp"
        android:background="@drawable/defaultuser_icon" />

    <EditText
        android:id="@+id/et_user_name"
        android:layout_width="fill_parent"
        android:layout_height="40dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginLeft="35dp"
        android:layout_marginRight="35dp"
        android:layout_marginTop="35dp"
        android:background="@drawable/textview_borders"
        android:drawableLeft="@drawable/user_name_icon"
        android:drawablePadding="10dp"
        android:gravity="center_vertical"
        android:hint="请输入用户名"
        android:paddingLeft="8dp"
        android:singleLine="true"
        android:textColor="#000000"
        android:textColorHint="#a3a3a3"
        android:textSize="14sp" />

    <EditText
        android:id="@+id/et_psw"
        android:layout_width="fill_parent"
        android:layout_height="40dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginLeft="35dp"
        android:layout_marginRight="35dp"
        android:background="@drawable/textview_borders"
        android:layout_marginTop="5dp"
        android:drawableLeft="@drawable/psw_icon"
        android:drawablePadding="10dp"
        android:hint="请输入密码"
        android:inputType="textPassword"
        android:paddingLeft="8dp"
        android:singleLine="true"
        android:textColor="#000000"
        android:textColorHint="#a3a3a3"
        android:textSize="14sp" />

    <Button
        android:id="@+id/btn_login"
        android:layout_width="fill_parent"
        android:layout_height="40dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginLeft="35dp"
        android:layout_marginRight="35dp"
        android:layout_marginTop="15dp"
        android:background="@color/colorPrimary"
        android:text="登 录"
        android:textColor="@android:color/white"
        android:textSize="18sp" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_marginLeft="35dp"
        android:layout_marginRight="35dp"
        android:layout_marginTop="8dp"
        android:gravity="center_horizontal"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/tv_register"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_horizontal"
            android:padding="8dp"
            android:text="立即注册"
            android:textColor="@color/colorPrimary"
            android:textSize="14sp" />

        <TextView
            android:id="@+id/tv_find_psw"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_horizontal"
            android:padding="8dp"
            android:text="找回密码?"
            android:textColor="@color/colorPrimary"
            android:textSize="14sp" />
    </LinearLayout>

</LinearLayout>

SPSaceInfo.java文件

public class SPSaveInfo {
    public static boolean saveInfoToSP(Context context, String userName, String userPwd) {
        SharedPreferences preferences = context.getSharedPreferences("data", Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = preferences.edit();
        editor.putString("userName", userName);
        editor.putString("userPwd", userPwd);
        editor.commit();
        return true;
    }

    public static Map<String, String> getInfoFromSP(Context context) {
        HashMap<String, String> hashMap = new HashMap<>();
        SharedPreferences preferences = context.getSharedPreferences("data", Context.MODE_PRIVATE);
        String userName = preferences.getString("userName", "");
        String userPwd = preferences.getString("userPwd", "");
        hashMap.put("userName", userName);
        hashMap.put("userPwd", userPwd);
        return hashMap;
    }
}

执行后可以发现点击登录之后会在文件管理器中发现有保存了xml文件。

内容总结:本文通过学习安卓零基础开发到入门的书籍,介绍了安卓的两种数据存储的方式,一种是内部存储空间文件的存取,另一种是SD卡空间的文件的存取。通过简单的介绍实现了不同方式的功能实现,使用java代码进行开发,后续内容可以继续追踪博主的后续文章,或许会介绍相关的内容,如果没介绍,请用力踢一脚,好让摸鱼的博主积极主动的去认识错误并及时改正,在发光发热的道路上越走越远……如果觉得本篇文章介绍的不错,也希望能得到您的一件三连,实不相瞒,三连确实有点费劲,我自己也很少给,或许你可以试试两连,这个还不错,我经常这样做。好了好了,这篇文章就扯到这里,再多怕被嫉妒,谢谢你这么认真的读完。如果觉得只是一键两连有点少了,你实在是想用金钱来收买我这颗孤独寂寞的心灵,那我也来者不惧,勉为其难的挂上一些自己的二维码,可是要记得千万别用支付宝扫微信的码喔,那样真的可就擦肩而过了,别给你机会你不中用哈,千万千万记得!再加一句,如果有好看的运营小姐姐,也不要吝啬把微信推给我,万一您推荐了那个真命女子,博主后大半辈子感谢你大半辈子。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NoSuchManException

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值