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();




            }
        });

    }
}
相关推荐
千里马学框架4 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台4 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone4 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc4 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo4 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077004 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼4 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone4 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen4 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone4 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui