本文最后更新于 2024-07-01,文章内容可能已经过时。

移动开发技术

1.Android概述:

1.1 介绍:

2008年9月,google发布Android 1.0;它是第一个免费、开源的手机操作系统;基于Linux内核,使用Java语言开发;

image-20240630150638948

1.2. 体系结构:

image-20240630211056082

image-20240630150755498

1.2.1 应用程序层:

Android平台的应用层上包括各类与用户直接交互的应用程序,或由java语言编写的运行于后台的服务程序。

1.2.2 应用程序框架层:

主要包含以下组件:

image-20240630150857610

1.2.3 系统运行库层:

程序库:C库、媒体库、Surface Manager、WebKit、SGL、3Dlibraries、FreeType、SSL、SQLite等。

Android 运行库:每一个Android应用程序都在它自己的进程中运行,都拥有一 个独立的Dalvik虚拟机实例。

Dalvik虚拟机依赖于linux内核的一些功能,比如线程机制和 底层内存管理机制。

1.2.4 linux内核层:

Android的核心系统服务依赖于Linux内核,如安全性,内存管理,进程管理,网络协议栈和驱动模型。

Linux内核也同时作为硬件和软件栈之间的抽象层。

1.3 系统特点:

  • Android将界面设计与程序逻辑分离,界面布局使用XML文件,有利于界面的修改和维护;

  • Android提供轻量级的进程间通讯机制Intent,使跨进程组件通 信和发送系统广播成为可能;

  • 在内存和进程管理方面,Android有自己的运行时和虚拟机;

  • Android提供Service作为无用户界面、长时间后台运行组件;

  • 支持快速、高效的数据存储:SharedPreferences、文件存储、SQLite数据库

  • 为了跨进程共享数据,Android提供ContentProvider接口 可以无需了解数据源、路径的情况下,对共享数据进行查询、添加、删除和更新等操作

2.环境搭建:

2.1 安装Android Studio:

2.2 配置Android SDK:

第一次运行时需配置

2.3 安装Intel HAXM:

为支持Intel VT虚拟技术(Virtualization Technology)的硬件加速。

2.4 配置Android Studio:

image-20240630151451548

3.项目的创建和运行:

3.1 项目创建:

image-20240630151548671

3.2 项目运行:

3.2.1 在模拟器AVD上运行程序:

AVD:Android Virtual Device,Android模拟器

AVD可以让开发人员不需使用物理设备即可预览、开发和测试Android应用程序。

3.2.2 在实际设备上运行:

3.2.3 项目结构:

image-20240630152802015

3.2.3.1 AndroidManifest.xml:

每一个Android项目都有一个名为AndroidManifest.xml的配置文件,在所有项目中该文件的名称不变。

该文件是Android工程的一个全局配置文件,所有在项目 中使用的组件(如 Activity,Service,Content provider和Broadcast receivers等)都要在该文件中声明。

该文件还可以声明一些android权限等信息。

4.Activity:

在安卓开发中,Activity 是一个应用程序的基本组件之一,代表一个单一的屏幕,包含用户可以与之交互的用户界面。每个 Activity 通常用于一个特定的任务或功能,在一个应用程序中可能包含多个 Activity,这些 Activity 之间可以通过 Intent 进行导航和数据传递。

通常一个界面布局对应一个Activity ,但一个Activity不一定对应一个界面布局。

4.1 主要功能:

1.用户界面展示:每个 Activity 都有自己的布局文件(XML 文件),定义了这个屏幕的 UI 元素(如按钮、文本框等)。

2.用户交互处理:Activity 响应用户的输入,如触摸、点击和键盘事件,并根据这些输入执行相应的操作。

3.生命周期管理:Activity 有一系列的生命周期方法(如 onCreate, onStart, onResume, onPause, onStop, onDestroy),用于管理 Activity 从创建到销毁的整个过程。这些方法帮助开发者管理资源、保存状态以及在适当的时间执行任务。

4.2 生命周期:

Activity生命周期指Activity从启动到销毁的过程

Activity表现为四种状态:

  1. 活动状态Active:Activity在用户界面中处于最上层,完全能被用户看到,能够与用户进行交互。

  2. 暂停状态Pause:Activity在界面上被部分遮挡,不再处于用户界面的最上层,且不能够与用户进行交互。(如弹出选择框时)

  3. 停止状态Stop:Activity被其他Activity全部遮挡,界面完全不 能被用户看到。(如玩游戏时来电了

  4. )非活动状态Dead:Activity没有启动或者被finish()。

    image-20240630152610198

随着Activity自身状态的变化,Android系统会调用不同的事件回调函数(7个):

  1. onCreate():当 Activity 首次创建时调用。在这个方法中,通常完成基本的应用初始化逻辑,比如设置布局文件,初始化组件等。

  2. onStart():当 Activity 变得可见时调用。在此方法中,应用程序可以执行一些初始化操作,比如开始动画等。

  3. onResume():当 Activity 开始与用户交互时调用。此时 Activity 处于前台,是用户可以操作的状态。

  4. onPause():当系统准备去启动或恢复另一个 Activity 时调用。在此方法中,应该保存数据,停止动画或其他 CPU 密集型操作,以便用户可以更快地返回 Activity。

  5. onStop():当 Activity 不再可见时调用。在此方法中,可以执行一些较重的资源释放工作。

  6. onDestroy():在 Activity 被销毁前调用,释放所有资源,清理内存。

  7. onRestart():在 Activity 从停止状态重新启动前调用。在此方法中,可以重新初始化被 onStop 方法释放的资源。

5.调试:

Android程序使用断点调试有时可能不好(如多线程程序)。

故通常使用日志文件来记录调试信息。

Android提供一个静态Log类,利用Log类的相关方法,将 调试信息写入日志文件。

LogCat工具可以实时查看日志信息。

image-20240630153016031

下面给出一个示例:

image-20240630153129495

查看log信息:

image-20240630153156359

6.Intent:

6.1 介绍:

  1. 启动其他的Activity

  2. 实现它们之间的单/双向通信。

Intent是一种组件之间消息传递机制,它是一个动作的完整描述:包含了动作产生组件、接收组件和传递的数据信息。

image-20240630153333775

6.2 使用Intent启动Activity:

6.2.1 显式启动:

image-20240630153515926

6.2.2 隐式启动:

无需指明具体启动哪一个Activity,而由Android系统根据Intent的动作和数据来决定启动哪一个Activity。

例如:希望启动一个浏览器,却不知道具体应该启动哪一 个Activity,此时则可以使用Intent的隐式启动,由Android 系统决定启动哪一个Activity来接收这个Intent。

隐式启动的可以是Android系统内置的Activity,也可是程 序本身的Activity,还可

是第三方应用程序的Activity。

image-20240630154012603

image-20240630154030813

6.3 数据传递:

6.3.1 单向数据传递:

通过在intent里面放ky对的方式去做。

image-20240630154245053

Bundle类是一个存储和管理key-value值对的类,多应用于Activity之间相互传递值。

6.3.1.1 传递对象:

Bundle可以传递对象,但前提是这个对象需要序列化(一种用来处理对象流的机制, 以解决如网络传播、磁盘读写等对对象流读写操作时所引发的问题。)

Bundle的putSerializable()方法,可以存储已经序列化的对象数据(仍然是Key-Value形式);

接收数据时Bundle用getSerializable()方法,获得数据需要强制转化一下原来的对象类型。

image-20240630154500885

image-20240630154521084

6.3.2 双向数据传递:

工作原理:

image-20240630154759821

代码框架: image-20240630154855777

image-20240630154942429

6.4 使用:

 // 显示注册信息的Toast消息
    String info = "用户名: " + username + "\n" +
                  "密码: " + userPassword + "\n" +
                  "性别: " + userSex + "\n" +
                  "联系电话: " + userTel + "\n" +
                  "部门: " + userDept + "\n" +
                  "爱好: " + userFavs;
    //系统提示符
    Toast.makeText(this, info, Toast.LENGTH_LONG).show();
​
    // 启动ResultActivity并传递数据
    Intent intent = new Intent(MainActivity.this, ResultActivity.class);
    intent.putExtra("userInfo", info);
    startActivity(intent);

使用:

// 获取传递的数据
String userInfo = getIntent().getStringExtra("userInfo");
​
// 获取TextView组件
resultTextView = findViewById(R.id.resultTextView);
​
// 显示传递的数据
resultTextView.setText(userInfo);

7.用户界面:

7.1 介绍:

用户界面UI(User Interface)是系统和用户之间进行信息交换的媒介。

7.1.1 应解决的问题:

  1. 界面设计与程序逻辑完全分离:这不仅有利于并行开发,而且在后期修改界面时,不用再次修改程序的逻辑代码

  2. 根据不同型号的屏幕能自动调整界面元素的位置和尺寸:避免因为屏幕信息的变化而出现显示错误

  3. 增强用户体验:能够合理利用较小的屏幕显示空间,构造出符合人机交互规律的用户界面

7.2 MVC模式:

image-20240630180931689

7.3 页面基本组件:

7.3.1 TextView:

用于显示信息。

image-20240630181225479

在程序中控制:

image-20240630181250216

7.3.2 ImageView:

用于显示图片。

7.3.3 Button:

按钮。

image-20240630181408649

7.3.4 EditText:

文本框,用于输入和编辑字符串。

image-20240630181559246

在程序中控制:

image-20240630181633767

7.3.5 RadioButton:

单选按钮须归属一个组,每个组只能有一个选项被选中。

所以通常使用的是RadioGroup。

image-20240630181756851

7.3.6 CheckBox:

复选框。

image-20240630181859949

7.3.7 Spinner:

下拉框:

image-20240630181937349

7.3.8 listview:

列表框。

ListView通常使用适配器来填充数据和设置显示样式。

7.4 adapter:

Adapter是连接后端数据和前端显示的适配器接口,是数据和UI(View)之间一个重要的纽带。

在常见的View(ListView,GridView)等地方都需要用到Adapter。

image-20240630182140261

7.5 界面布局:

7.5.1 相对布局:RelativeLayout

相对布局是一种非常灵活的布局方式;

通过指定界面元素与其他元素的相对位置关系,来确定界面中所有元素的布局位置;

优点:能够最大程度保证在各种屏幕尺寸的手机上正确显示界面布局。

7.5.2 线性布局:LinearLayout:

线性布局是常用的一种布局方式;

通过设置android:orientation来确定是垂直还是水平布局:

android:orientation="vertical 垂直布局:每行仅包含一个界面元素
​
android:orientation="horizontal 水平布局 (默认):所有界面元素都在一行

7.5.3 框架布局:FrameLayout:

FrameLayout中所有界面对象都是从屏幕的左上角(0,0)开始布局,不能指定位置;

多个组件层叠排列,上一层的会覆盖下一层的控件;

第一个添加的组件放到最底层,最后添加的显示在最上面。

7.5.4 表格布局:

表格布局以行列的形式管理子元素,每一行是一个TableRow布局对象,当然也可以是普通的View对象;

TableRow表现为一个水平LinearLayout,里面的元素会 水平排列。

image-20240630182707693

7.5.5 网格布局:GridLayout

Android4.0新支持的布局;

网格布局将用户界面划分为网格,界面元素可随意摆放在网格中,网格布局比表格布局更灵活;

在网格布局中界面元素可以占用多个网格。

7.5.6 绝对布局:AbsoluteLayout:

绝对布局能通过指定界面元素的坐标位置,来确定用户界面的整体布局。已经不推荐使用。

绝对布局不能够根据不同屏幕对界面元素进行位置调整。

7.6 界面菜单:

7.6.1 选项菜单:

Android手机上有个Menu键,当Menu按下的时候,在屏幕底部弹出一个菜单,这个菜单就叫OptionsMenu。每个Activity有且只有一个OptionsMenu,它为整个Activity服务。

image-20240630183046227

7.6.2 上下文菜单:

上下文菜单类似Windows中的鼠标右键弹出菜单;

上下文菜单一般是通过长按(大约2秒)屏幕弹出。

image-20240630183232784

7.7 编写方式:

项目整体分包如下:

image-20240630220930898

7.7.1 activity_main.xml:

比如要编写主页面的逻辑,在activity_main.xml中编写。

文件内容如下:

<?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">
​
    <!-- 用户名标签 -->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="用户名"
        android:textSize="20dp"
        />
    <!-- 用户名输入框 -->
    <EditText
        android:id="@+id/name"
        android:layout_width="400dp"
        android:layout_height="50dp"
        />
    
    <!-- 密码标签 -->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="密码"
        android:textSize="20dp"
        />
    <!-- 密码输入框 -->
    <EditText
        android:id="@+id/password"
        android:layout_width="400dp"
        android:layout_height="50dp"
        android:inputType="textPassword"
        />
    
    <!-- 性别标签 -->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="性别"
        android:textSize="20dp"
        />
    <!-- 性别单选按钮组 -->
    <RadioGroup
        android:id="@+id/sex"
        android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <!-- 男性单选按钮 -->
        <RadioButton
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            android:id="@+id/man"
            android:text="男"
            android:textSize="20dp"/>
        <!-- 女性单选按钮 -->
        <RadioButton
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            android:id="@+id/woman"
            android:text="女"
            android:textSize="20dp"/>
    </RadioGroup>
    
    <!-- 联系电话标签 -->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="联系电话"
        android:textSize="20dp"
        />
    <!-- 联系电话输入框 -->
    <EditText
        android:id="@+id/tel"
        android:layout_width="400dp"
        android:layout_height="wrap_content"
        android:inputType="text|phone"
        />
    
    <!-- 部门标签 -->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="部门"
        android:textSize="20dp"
        />
    <!-- 部门下拉菜单 -->
    <Spinner
        android:id="@+id/dept"
        android:layout_width="400dp"
        android:layout_height="50dp"
        android:entries="@array/dept"
        />
    
    <!-- 爱好标签 -->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="爱好"
        android:textSize="20dp"
        />
    <!-- 爱好复选框组 -->
    <LinearLayout
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:orientation="horizontal">
        <!-- 书籍复选框 -->
        <CheckBox
            android:id="@+id/book"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="书籍"
            android:textSize="20dp"/>
        <!-- 运动复选框 -->
        <CheckBox
            android:id="@+id/sport"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="运动"
            android:textSize="20dp"/>
        <!-- 音乐复选框 -->
        <CheckBox
            android:id="@+id/music"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="音乐"
            android:textSize="20dp"/>
        <!-- 电影复选框 -->
        <CheckBox
            android:id="@+id/movie"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="电影"
            android:textSize="20dp"/>
    </LinearLayout>
    
    <!-- 确定按钮 -->
    <Button
        android:id="@+id/ok"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="确定"
        android:onClick="myclick"
        />
      //从文件读取
         <Spinner
        android:id="@+id/dept"
        android:layout_width="400dp"
        android:layout_height="50dp"
        android:entries="@array/dept"
        />
​
</LinearLayout>

LinearLayout的orientation 属性设置为 vertical,这意味着所有子视图将垂直排列。如果需要特殊指定,在大的内部添加新的LinearLayout标签。

7.7.2 activity.main:

package com.example.myapp;
​
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
​
public class MainActivity extends AppCompatActivity {
​
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //在这里绑定xml文件
        setContentView(R.layout.activity_main);
    }
​
    // 用于登录的方法
    public void login(View view) {
        // 显示登录的Toast消息
        Toast.makeText(this, "登录操作", Toast.LENGTH_SHORT).show();
    }
​
    // 用于处理忘记密码的方法
    public void forgetPass(View view) {
        // 显示忘记密码的Toast消息
        Toast.makeText(this, "忘记密码操作", Toast.LENGTH_SHORT).show();
    }
​
    // 用于打开注册界面的方法
    public void register(View view) {
        // 显示注册的Toast消息
        Toast.makeText(this, "打开注册界面操作", Toast.LENGTH_SHORT).show();
    }
​
    // 确定按钮点击事件处理方法
    public void myclick(View view) {
        // 显示确定操作的Toast消息
        Toast.makeText(this, "确定操作", Toast.LENGTH_SHORT).show();
    }
}

在xml中,通过onclick标签指定按钮具体绑定的方法:

    <!-- 注册按钮 -->
    <Button
        android:id="@+id/register"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="注册"
        android:onClick="register"
        />

7.7.3 获取对象的id:

 //初始化
 private EditText name, password, tel;
 private RadioGroup sex;
 private Spinner dept;
 private ArrayList<CheckBox> favs = new ArrayList<>();
 private Button ok;
 
 //读取相关方法:
  // 获取性别方法
 private String getSex() {
      int selectedId = sex.getCheckedRadioButtonId();
      RadioButton selectedRadioButton = findViewById(selectedId);
      return selectedRadioButton.getText().toString();
  }

8.广播机制:

在Android中,广播(Broadcast)是一种广泛运用在应用程序之间传输信息的机制。

广播消息实质就是将一个Intent对象用sendBroadcast方法发送出去。

Android的每个应用程序都可以对自己感兴趣的广播进行注册,只自己所关心的广播内容。

8.1 BroadcastReceiver:

BroadcastReceiver是对发送出来的Broadcast进行过滤并响应的一类组件,是Android系统的四大组件之一。一般要在AndroidManifest.xml中注册。

8.2 广播类型:

8.2.1 系统广播:

系统广播就是由Android系统发出的广播。

如系统启动完成了、系统关闭了、拨打电话了、收到短信 了、手机没电了、新安装了一个应用程序、在耳机口上插 入耳机、设备内存不足、屏幕关闭等等。

8.2.1.1 示例:

在gui中创建广播接收器BroadcastReceiver,生成的代码框架:

image-20240630184008697

编写完成具体的代码之后,在AndroidManifest.xml中进行注册:

image-20240630184057323

8.2.2 自定义广播:

8.2.2.1 发送:

在广播发送端(如某个APP的Activity),把信息装入一个Intent对 象(含一个自定义的消息标识串,值任意,能保证唯一性即可), 然后sendBroadcast(intent)把 Intent 广播出去。

image-20240630184205212

8.2.2.2 接收:

接收端创建Broadcast Receiver。并编写onReceive()方法。

image-20240630184256660

消息广播标识串,自定义值,具有唯一性即可。

9.Service:

Service是Android系统四大组件之一,它是一种长生命周期的,没有可视化界面,运行于后台的一种服务程序。

9.1 类型:

9.1.1 Started启动的:常用于应用程序内部:

Started形式是指当一个应用组件(如Activity)通过startService()方法 开启的服务。一旦开启,该服务就可以无限期地在后台运行,哪怕 开启它的组件被销毁。

在应用程序中定义service组件。服务通过调用startService(intent)启动,stopService(intent)结束。在服务内部可以调用stopSelf() 来自己停止。

通常,开启的服务执行一个单独的操作且并不向调用者返回一个结果。无论调用了多少次startService(),只需调用一次stopService()来停止。

9.1.2 Bound绑定的:用于应用程序之间:

Bound形式是指一个应用组件通过调用 bindService() 方法与服务绑定。调用 unbindService()关闭连接。

多个组件可以同时绑定到一个服务,但当全部绑定解除后,服务 就被销毁。

9.1.3 生命周期:

image-20240630211421780

9.1.4 编写流程:

1.使用GUI创建一个service。

2.在生成的代码框架中编写代码

image-20240630211758167

10.数据存储和访问:

10.1 简单数据存储:

应用程序一般允许用户自己定义配置信息,如界面背景颜色、字体大小和字体颜色等。

使用SharedPreferences保存用户的自定义配置信息,并在程序启动时自动加载这些自定义的配置信息。

10.2 SharedPreferences:

SharedPreferences是一种轻量级的数据保存方式。

通过SharedPreferences可以将NVP(Name/Value Pair,名称/值对)保存在Android的文件系统中,而且SharedPreferences完全屏蔽的对文件系统的操作过程。开发人员仅是通过调用SharedPreferences对NVP进行保存和读取。

SharedPreferences不仅能够保存数据,还能够实现不同应用程序间的数据共享。

10.2.1 访问模式:

  1. 私有(MODE_PRIVATE):仅有创建程序有权限对其进行读取或写入。

  2. 全局读(MODE_WORLD_READABLE):不仅创建程序可以对其进行读取或写入,其他应用程序也读取操作的权限,但没有写入操作的权限。

  3. 全局写(MODE_WORLD_WRITEABLE):创建程序和其他程序都可以对其进行写入操作,但没有读取的权限。

10.2.2 使用:

10.2.2.1 定义变量:

//私有模式
public static int MODE = MODE_PRIVATE;
//混合模式
public static int MODE = Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE;
​
//定义名称
public static final String PREFERENCE_NAME = "SaveSetting";

10.2.2.2 创建SharedPreferences对象:

SharedPreferences sharedPreferences = getSharedPreferences(PREFERENCE_NAME, MODE);

10.2.2.3 使用:

在获取到SharedPreferences对象后,则可以通过SharedPreferences.Editor对象对SharedPreferences进行修改,最后调用commit()函数保存修改内容。

SharedPreferences广泛支持各种基本数据类型,包括整型、布尔型、浮点型和长型等等。

SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("Name", "Tom");
editor.putInt("Age", 20);
editor.putFloat("Height", );
editor.commit();

如果需要从已经保存的SharedPreferences中读取数据,同样是调用getSharedPreferences()函数,并在函数的第1个参数中指明需要访问的SharedPreferences名称,最后通过get<Type>()函数获取保存SharedPreferences中的NVP。

SharedPreferences sharedPreferences = getSharedPreferences(PREFERENCE_NAME, MODE);
String name = sharedPreferences.getString("Name","Default Name");
int age = sharedPreferences.getInt("Age", 20);
float height = sharedPreferences.getFloat("Height",);

get<Type>()函数的第1个参数是NVP的名称。第2个参数是在无法获取到数值的时候使用的缺省值。

10.3 文件存储:

Android使用的是基于Linux的文件系统。

程序开发人员可以建立和访问程序自身的私有文件。也可以访问保存在资源目录中的原始文件和XML文件。还可以在SD卡等外部存储设备中保存文件。

10.3.1 内部存储:

Android系统允许应用程序创建仅能够自身访问的私有文件,文件保存在设备的内部存储器上,在Linux系统下的/data/data/<package name>/files目录中。

Android系统不仅支持标准Java的IO类和方法,还提供了能够简化读写流式文件过程的函数。

10.3.1.1 openFileOutput()函数:

openFileOutput()函数为写入数据做准备而打开的应用程序私文件,如果指定的文件不存在,则创建一个新的文件。

文件模式:

MODE_PRIVATE

私有模式,缺陷模式,文件仅能够被文件创建程序访问,或具有相同UID的程序访问。

MODE_APPEND

追加模式,如果文件已经存在,则在文件的结尾处添加新数据。

MODE_WORLD_READABLE

全局读模式,允许任何程序读取私有文件。

MODE_WORLD_WRITEABLE

全局写模式,允许任何程序写入私有文件。

10.3.1.2 openFileInput()函数:

openFileInput()函数为读取数据做准备而打开应用程序私文件。

10.3.2 外部存储:

编程访问SD卡首先需要检测系统的/sdcard目录是否可用。如果不可用,则说明设备中的SD卡已经被移除,

在Android模拟器则表明SD卡映像没有被正确加载。如果可用,则直接通过使用标准的Java.io.File类进行访问。

将数据保存在SD卡通过“生产随机数列”按钮生产10个随机小数。通过“写入SD卡”按钮将生产的数据保存在SD卡的目录下。SDcardFileDemo示例说明了如何将数据保存在SD卡。

11.ContentProvider:

Android应用程序运行在不同的进程空间中,因此不同应用程序的数据是不能够直接访问的。

ContentProvider提供了应用程序之间共享数据的方法。 一个应用程序可以通过ContentProvider将自己的数据暴露出去。

应用程序通过ContentProvider访问数据而不需要关心数据具体的存储及访问过程,这样既提高了数据的访问效率,同时也保 护了数据。

应用程序使用 ContentResolver 对象,利用URI,才能访问ContentProvider提供的数据集。

11.1 数据:

ContentProvider可以形象地看作是"数据库"。ContentProvider数据集类似于数据库的"表"。ContentProvider数据集的每条记录都包含一个long型的字 段_ID,用来唯一标识每条记录。

image-20240630214407459

11.2 URL:

URI:统一资源标识符(Uniform Resource Identifier),用来标识资源的逻辑位置。(定义远程或本地的可用资源)

每一个Content Provider 都对外提供一个能够唯一标识自己 数据集的公开URI;如果一个Content Provider管理多个数据集,则应给每个数据集分配一个独立的URI

11.2.1 格式:

image-20240630214525759

举个例子:

image-20240630214625580

11.3 使用:

//创建
ContentResolver resolver = getContentResolver();
​
//crud:
resolver.query()、insert()、update()、delete()

11.3.1 提供端:

image-20240630214844487