Android手把手编写儿童手机远程监控App之SQLite详解

概述

上节详细描述通过Application 类全局获取Context,使得在程序开发中任何地方如Utils、ViewModel、Repository 轻松拿到Context,而不需要层层传递。

通过两步实现全局Context

  • 创建自定义 Application 类
  • 在 AndroidManifest.xml 中注册 嘟宝app启动,首先生成自定义 Application 类的实力,拿到Context。
clike 复制代码
public class app extends Application {
    private static Context context;

    @Override
    public void onCreate() {
        super.onCreate();
        context = getApplicationContext();
    }
    public static Context getContext() {
        return context;
    }
}
<application
    android:name=".MyApplication"  <!-- 关键:注册自定义 Application -->
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name">
    
    <!-- 你的 Activity、Service 等组件 -->
    
</application>

可在任何地方,使用app.getContext获取Context。 目前嘟宝完成的功能,开机自动启,启动前台服务建立连接mqtt长连接。通过二维码显示身份识别码(uuid),嘟妈通过二维码扫描绑定。嘟宝收到绑定指令后,发送消息通知栏引导用户确认。 用户绑定信息后,需要将嘟妈信息存储本地。一旦完成绑定,嘟妈可以发送信令,完成麦克、摄像头查看,嘟宝收到信令根本本地存储信息健全,将音视频通过一对一通道发送嘟妈。

SQLite

SQLite 是一款轻量级、零配置、嵌入式的关系型数据库引擎,自 Android 系统诞生之初就被内置支持。它的核心特点包括:

  • 轻量级,完全配置时小于 400KiB可选功能配置时小于 250KiB
  • 零配置,无需安装、无需管理、无需独立的服务器进程
  • 单文件存储,整个数据库存储在一个跨平台的磁盘文件中
  • ACID 兼容,支持原子性、一致性、隔离性、持久性事务
  • SQL 支持,支持 SQL92 标准的大部分查询语言功能
  • 跨平台,可在 Android、iOS、Windows、Linux、macOS 等平台运行 SQLite 的特性使其非常适合移动端应用场景,不需要单独部署数据库服务器,而是以单个存储在每个应用的私有目录中,方便迁移。

SQLite数据库创建

Android 通过SQLiteOpenHelper类管理数据库。负责数据库的创建与版本管理。嘟宝存储嘟妈绑定信息,表duma设计应包含是以下几个字段

  • id主键,类型
  • dumaName嘟妈别称
  • dumaId嘟妈uuid,嘟妈身份识别码
  • bindDateTime绑定时间 字段名称,字段类型SQLite含有类型
存储类型 描述
NULL 空值,缺省状态
INTEGER 有符号整数
REAL 浮点数
TEXT 文本字符串
BLOB 二进制大对象,按原始字节存储,用于图片文件存储
数据库表,duma创建的SQL语句
clike 复制代码
CREATE TABLE duma (
  id INTEGER PRIMARY KEY AUTOINCREMENT, 
	dumaName text,
  dumaId text,
  bindDateTime INTEGER
)

id主键自增,bindDateTime 为整数,SQLite没有日期类型。用时间戳作为类型

创建事例

  • 创建类MyDB,继承SQLiteOpenHelper
  • 在MainActivity通过点击按钮创建数据库dubao与表duma 创建类MyDB,如下图 MyDB类源码
clike 复制代码
package com.zilong.dubao;

import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;

public class MyDB extends SQLiteOpenHelper {
    public MyDB( String name, SQLiteDatabase.CursorFactory factory,
                int version){
        super(app.getContext(), name, factory, version);


    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        Toast.makeText(app.getContext(),"数据库与表创建成功",Toast.LENGTH_SHORT).show();
        String dumaTabel="CREATE TABLE duma (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, dumaName text,dumaId text,bindDateTime INTEGER)";
        db.execSQL(dumaTabel);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

在MyDB构造函数中,调用父类构造函数 super(app.getContext(), name, factory, version);参数有四

  • Context Android 上下文
  • name,数据库名称
  • factory用于创建查询返回的 Cursor 对象
  • version版本号,用于对数据库升级。 MainActivity源码
clike 复制代码
package com.zilong.dubao;
import androidx.appcompat.app.AppCompatActivity;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
    private MyDB myDB=new MyDB("dubao.db",null,1);
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initBtn();
    }
    private void initBtn(){
        Button createDBBtn=findViewById(R.id.createDB);
        createDBBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myDB.getWritableDatabase();

            }
        });
    }
}

运行代码 当首次点击按钮时,程序调用MyDB onCreate函数,生成数据库dubao,并创建表duma,再次点击时,不再调用,原因在数据库已经创建。 若要引起数据库的创建,需要将构造函数中version版本号增加。

插入数据

MyDB类不变,在MainActivity增加按钮,插入新数据 MainActivity源码

clike 复制代码
package com.zilong.dubao;
import androidx.appcompat.app.AppCompatActivity;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
    private MyDB myDB=new MyDB("dubao.db",null,12);
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initBtn();

    }
    private void initBtn(){
        Button createDBBtn=findViewById(R.id.createDB);
        createDBBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myDB.getWritableDatabase();

            }
        });
        Button InsertBtn=findViewById(R.id.insertDB);
        InsertBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db =myDB.getWritableDatabase();
                ContentValues values = new ContentValues();
                values.put("dumaName","嘟妈一号");
                values.put("dumaId","f1122aeb-f2b0-400d-9919-eddd2eaebaa2");
                values.put("dumaName","嘟妈一号");
                values.put("bindDateTime",System.currentTimeMillis());
                db.insert("duma",null,values);

            }
        });

    }
}

运行结果 点击按钮,插入一条数据。

查新数据

clike 复制代码
package com.zilong.dubao;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private MyDB myDB=new MyDB("dubao.db",null,12);
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initBtn();
    }
    private void initBtn(){
        Button createDBBtn=findViewById(R.id.createDB);
        createDBBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myDB.getWritableDatabase();

            }
        });
        Button insertBtn=findViewById(R.id.insertDB);
        insertBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db =myDB.getWritableDatabase();
                ContentValues values = new ContentValues();
                values.put("dumaName","嘟妈一号");
                values.put("dumaId","f1122aeb-f2b0-400d-9919-eddd2eaebaa2");
                values.put("dumaName","嘟妈一号");
                values.put("bindDateTime",System.currentTimeMillis());
                db.insert("duma",null,values);

            }
        });
        Button queryBtn=findViewById(R.id.queryDB);
        queryBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db =myDB.getWritableDatabase();
                Cursor cursor = db.rawQuery("SELECT * FROM duma", null);
                if (cursor.moveToFirst()){
                    do{
                        @SuppressLint("Range") String dumaName=cursor.getString(cursor.getColumnIndex("dumaName"));
                        @SuppressLint("Range") String dumaId=cursor.getString(cursor.getColumnIndex("dumaId"));
                        Toast.makeText(MainActivity.this,dumaId+dumaName,Toast.LENGTH_SHORT).show();

                    }while (cursor.moveToNext());
                }
               cursor.close();




            }
        });

    }

}

运行结果

使用SQL操作数据库

虽然Andorid提供非常多的api操作数据,但直接使用SQL语句操作数据库,才是最便捷舒适。 增删改使用db.execSQL(sql),查询使用rawQuery 重新更改MainActivity源码

clike 复制代码
package com.zilong.dubao;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private MyDB myDB=new MyDB("dubao.db",null,12);
    private int index=0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initBtn();
    }
    private void initBtn(){
        Button createDBBtn=findViewById(R.id.createDB);
        createDBBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myDB.getWritableDatabase();

            }
        });
        Button insertBtn=findViewById(R.id.insertDB);
        insertBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db =myDB.getWritableDatabase();
                String sql="";
                sql=String.format("INSERT INTO duma( \"dumaName\", \"dumaId\", \"bindDateTime\") VALUES ( '%s', '%s', '%d');","嘟妈"+index,"999"+index ,System.currentTimeMillis());
                Log.d("mqtt",sql);
                db.execSQL(sql);

            }
        });
        Button queryBtn=findViewById(R.id.queryDB);
        queryBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db =myDB.getWritableDatabase();
                Cursor cursor = db.rawQuery("SELECT * FROM duma", null);
                if (cursor.moveToFirst()){
                    do{
                        @SuppressLint("Range") String dumaName=cursor.getString(cursor.getColumnIndex("dumaName"));
                        @SuppressLint("Range") String dumaId=cursor.getString(cursor.getColumnIndex("dumaId"));
                        @SuppressLint("Range") int bindDateTime=cursor.getInt(cursor.getColumnIndex("bindDateTime"));
                        Toast.makeText(MainActivity.this,dumaId+dumaName+bindDateTime,Toast.LENGTH_SHORT).show();

                    }while (cursor.moveToNext());
                }
                cursor.close();




            }
        });

    }
}
相关推荐
therese_1008618 小时前
安卓面试题
android
码云骑士18 小时前
Android Launcher启动过程
android
Java面试题总结19 小时前
MySQL EXISTS 详解:存在性判断、NOT EXISTS 与实战示例
android·数据库·mysql
_李小白19 小时前
【android opencv学习笔记】Day 30: 滤波算法之拉普拉斯算子
android·opencv·学习
NiceCloud喜云1 天前
Opus 4.8 的 Effort Control 怎么选:Low 到 Max 五档策略
android·java·大数据·前端·c++·python·spring
日光明媚1 天前
一步生成视频!One-Forcing:DMD + 零成本 GAN,训练 200 步超越多步 SOTA
android·开发语言·kotlin
帅次1 天前
Android 17 开发者实战:核心更新与应用场景落地指南
android·java·ios·android studio·iphone·android jetpack·webview
大鹏说大话1 天前
SQL 排序与分组实战:解决“分组后取最新数据“
android·java·数据库
搜狐技术产品小编20231 天前
破局与重构:纯端侧 Android 自动化引擎的尝试与未来推演
android·运维·重构·自动化
码云骑士1 天前
Android SystemServer启动过程
android·systemserver