在AndroidManifest.xml文件中添加权限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
在AndroidManifest.xml文件中注册接收广播配置, 添加到manifest > application节点下
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.BOOT_COMPLETED">action>
intent-filter>
receiver>
在AndroidManifest.xml文件中添加节点属性, 指定安装目录为内部存储器, 而非SD卡
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="internalOnly">
开机启动执行代码
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
/**
* 接收开机广播
*/
public class MyReceiver extends BroadcastReceiver {
public MyReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
Intent i = new Intent(context, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
}
public class NetWorkUtil {
public static boolean checkNetworkState(MainActivity mainActivity) {
//使用ConnectivityManager检查网络状态步骤
ConnectivityManager connectivityManager = (ConnectivityManager) mainActivity.getSystemService(CONNECTIVITY_SERVICE);//1.通过系统服务获取ConnectivityManager类的对象
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();//2.调用getActiveNetworkInfo()获取当前活动的网络NetworkInfo对象
//3.判断当前网络状态是否为连接状态,如果当前没有网络是活动的,则返回null
if (networkInfo != null && networkInfo.isConnected()) {
MainActivity.toast.setText("您已连接网络");
MainActivity.toast.show();
MainActivity.timer.schedule(new TimerTask() {
@Override
public void run() {
String res = HttpUtil.get(URLConst.SERVER_URL);
if (res == null) {
MainActivity.timer.schedule(new TimerTask() {
@Override
public void run() {
MainActivity.toast.setText("您与服务器的通讯异常, 数据可能会同步失败!");
MainActivity.toast.show();
}
}, 3000);
} else {
Map map = JSONUtil.toObject(res, Map.class);
if (map.get("code").toString().startsWith("200")) {
MainActivity.timer.schedule(new TimerTask() {
@Override
public void run() {
MainActivity.toast.setText("您与服务器的通讯正常!");
MainActivity.toast.show();
}
}, 3000);
} else {
MainActivity.timer.schedule(new TimerTask() {
@Override
public void run() {
MainActivity.toast.setText("您与服务器的通讯异常, 数据可能会同步失败!");
MainActivity.toast.show();
}
}, 3000);
}
}
}
}, 1000);
return true;
} else {
MainActivity.toast.setText("您已断开网络");
MainActivity.toast.show();
return false;
}
// 检测和服务器之间的连接
}
}
MainActivity.this.runOnUiThread(() -> {
EditText edit = (EditText) findViewById(R.id.txt_msg);
String now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINESE).format(new Date());
long tid = Thread.currentThread().getId();
String txt = String.format("%s\r\n%s - %d: %s", edit.getText(), now, tid, msg);
edit.setText(txt);
edit.setSelection(edit.getText().length());
});
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
public class HttpUtil {
public static String postJson(String url, HashMap<String, String> headerMap, Object data) {
HttpURLConnection conn = null;
try {
Log.d("main", "请求准备" + url);
conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestMethod("POST");//设置POST请求方式
conn.setConnectTimeout(5000);//设置超时时间
conn.setRequestProperty("Content-Type", "application/json");
// if (data == null) {
// data = new Object();
// }
String jsonStr = JSONUtil.toJSONString(data);
Log.d("main", "请求准备 - 已添加参数" + jsonStr);
byte[] bytes = jsonStr.getBytes(StandardCharsets.UTF_8);
Log.d("main", "请求准备 - 参数大小" + bytes.length);
conn.setRequestProperty("Content-Length", String.valueOf(bytes.length));//设置请求头,设置提交数据的长度
if (headerMap != null) {
for (String key : headerMap.keySet()) {
conn.setRequestProperty(key, headerMap.get(key));
}
}
Log.d("main", "请求准备 - 已添加请求头");
conn.setDoOutput(true);//设置允许向外写数据
conn.connect();//连接
Log.d("main", "请求准备 - 连接");
//4.通过getOutputStream()获得输出流往服务器写数据
OutputStream outputStream = conn.getOutputStream();//通过getOutputStream()获得输出流
outputStream.write(jsonStr.getBytes());
Log.d("main", "请求准备 - 写入数据");
int code = conn.getResponseCode();//获取HTTP状态码
Log.d("main", "响应处理 - 获取状态码");
if (code == HttpURLConnection.HTTP_OK) {//5.得到响应码并判断连接正常后,通过getInputStream()方法获得携带服务器返回信息的输入流,从流中读取出服务器返回值,并向handler发送消息
System.out.println(conn.getResponseCode());//控制台输出
InputStream inputStream = conn.getInputStream();//得到响应流(通过getInputStream()方法获取携带服务器返回信息的输入流)
byte[] dataBytes = parseResponse(inputStream);
String msg = new String(dataBytes, StandardCharsets.UTF_8);
Log.d("main", msg);
return msg;
} else {
Log.d("main", "请求失败了" + conn.getResponseCode());
}
} catch (Exception e) {
e.printStackTrace();
Log.d("main", "请求异常了");
} finally {
if (conn != null) {
conn.disconnect();//关闭HTTP连接
}
}
return null;
}
public static String get(String url) {
HttpURLConnection conn = null;
try {
Log.d("main", "请求准备" + url);
conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);//设置超时时间
conn.connect();//连接
Log.d("main", "请求准备 - 连接");
int code = conn.getResponseCode();//获取HTTP状态码
Log.d("main", "响应处理 - 获取状态码");
if (code == HttpURLConnection.HTTP_OK) {//5.得到响应码并判断连接正常后,通过getInputStream()方法获得携带服务器返回信息的输入流,从流中读取出服务器返回值,并向handler发送消息
System.out.println(conn.getResponseCode());//控制台输出
InputStream inputStream = conn.getInputStream();//得到响应流(通过getInputStream()方法获取携带服务器返回信息的输入流)
byte[] dataBytes = parseResponse(inputStream);
String msg = new String(dataBytes, StandardCharsets.UTF_8);
Log.d("main", msg);
return msg;
} else {
Log.d("main", "请求失败了" + conn.getResponseCode());
}
} catch (Exception e) {
e.printStackTrace();
Log.d("main", "请求异常了" + e.getMessage());
} finally {
if (conn != null) {
conn.disconnect();//关闭HTTP连接
}
}
return null;
}
private static byte[] parseResponse(InputStream input) {
byte[] buff = new byte[1024];
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int len;
try {
while ((len = input.read(buff)) != -1) {
byteArrayOutputStream.write(buff, 0, len);
}
return byteArrayOutputStream.toByteArray();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
gson是谷歌…
implementation ‘gson-2.8.5’
依赖无法下载, 直接使用jar包, 将jar包放到libs目录下, 然后到build.gradle文件中, dependencies节点下添加implementation(fileTree(“libs”)); 然后创建工具类
import com.google.gson.Gson;
public class JSONUtil {
public static String toJSONString(Object o) {
Gson gson = new Gson();
return gson.toJson(o);
}
public static <T> T toObject(String json, Class<T> tClass) {
Gson gson = new Gson();
return gson.fromJson(json, tClass);
}
}
SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的,而且已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库管理系统来讲,它的处理速度比他们都快。SQLite第一个Alpha版本诞生于2000年5月。 至2021年已经接近有21个年头,SQLite也迎来了一个版本 SQLite 3已经发布。
从某种程度上说,SQLite最初的构思是在一条军舰上进行的。当时在通用动力工作的SQLite的作者 [1] D. Richard Hipp正在为美国海军编制一种使用在导弹驱逐舰上的程序。那个程序最初运行在Hewlett-Packard UNIX(HPUX)上,后台使用Informix数据库。对那个具体应用而言,Informix有点儿太强大了。一个有经验的数据库管理员(DBA)安装或升级Informix可能需要一整天,如果是没经验的程序员,这个工作可能永远也做不完。真正需要的只是一个自我包含的数据库,它易使用并能由程序控制传导,另外,不管其他软件是否安装,它都可以运行。
2000年1月,Hipp开始和一个同事讨论关于创建一个简单的嵌入式SQL数据库的想法,这个数据库将使用GNU DBM哈希库(gdbm)做后台,同时这个数据库将不需要安装和管理支持。后来,一有空闲时间,Hipp就开始实施这项工作,2000年8月,SQLite 1.0版发布了。
按照原定计划,SQLite 1.0用gdbm作为存储管理器。然而,Hipp不久就用自己实现的能支持事务和记录按主键存储的B-tree替换了gdbm。随着第一次重要升级的进行,SQLite有了稳定的发展,功能和用户也在增长。2001年中期,很多项目–开源的或商业的–都开始使用SQLite。在随后的几年中,开源社区的其他成员开始为他们喜欢的脚本语言和程序库编写SQLite扩展。一个接着一个,既Perl、Python、Ruby、Java和其他主流的程序设计语言的扩展之后,新的扩展如SQLite的ODBC接口出现并证明了SQLite的广泛应用和实用功能。
2004年,SQLite从版本2升级到版本3,这是一次重大升级。
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import androidx.annotation.Nullable;
/**
* MySqliteOpenHelper 工具类 单例模式(1.构造函数私有化,2.对外提供函数。)
*/
// 该类就可以理解为一个数据库了。
public class MySqliteOpenHelper extends SQLiteOpenHelper {
// 单例模式
private static SQLiteOpenHelper mInstance;
// 提供对外提供的函数。
public static synchronized SQLiteOpenHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new MySqliteOpenHelper(context, "security_detector.db", null, 1);
}
return mInstance;
}
/**
* 通过构造函数,将数据库名称,数据库版本号等定义出来。因此,必须要声明一个构造函数。
*
* @param context context就是环境,在此环境下进行创建数据库。
* @param name 数据库名称
* @param factory 工厂
* @param version 版本 数据库升级后需要不断加1操作!
*/
public MySqliteOpenHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
/**
* 数据库初始化用的:
* 创建表 表数据初始化 数据库第一次创建的时候调用。第二次发现有该表了就不会重复创建了!
* 此函数只会执行一次。 因此,添加了新的数据库或者修改了数据库,必须要对应项目目录将databases目录下的db等文件删除。
*
* @param sqLiteDatabase
*/
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
String sql = "create table serial_setting(" +
"_id integer primary key autoincrement," +
"updated_time DATETIME" +
")";
// 执行sql
sqLiteDatabase.execSQL(sql);
}
// 数据库升级用的
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
增删改都是执行execSQL, 查询用rawQuery
private void initScreenData() {
SQLiteOpenHelper helper = MySqliteOpenHelper.getInstance(this);
// 读数据
SQLiteDatabase db = helper.getReadableDatabase();
if (db.isOpen()) {
Cursor cursor = db.rawQuery("SELECT * FROM serial_setting;", null);
if (cursor.getCount() == 0) {
Log.d("main", "第一次加载, 开始初始化数据");
// 初始化
String sql = "insert into serial_setting(updated_time)";
sql += "values(?)";
Object[] args = new Object[]{
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINESE).format(new Date())
};
db.execSQL(sql, args);
} else {
try {
cursor.moveToNext();
int id = cursor.getInt(cursor.getColumnIndex("_id"));
String updatedTime = cursor.getString(cursor.getColumnIndex("updated_time"));
} catch (NumberFormatException e) {
e.printStackTrace();
Log.d("main", "设置数据库存储的数据失败, 可能有空值!");
}
}
cursor.close();
db.close();
}
}
同Java一样, 使用java.util.Timer
每个timer都是一个执行者, TimerTask是要完成的事, timer在启动时就会创建一个线程和队列用于执行内部队列任务, 执行schedule会添加任务到任务队列中
Timer timer = new Timer();
// 定时执行数据发送(如果存在)
timer.schedule(new TimerTask() {
@Override
public void run() {
if (System.currentTimeMillis() - bufferUpdatedTime >= intervalTime) {
// 超过更新时间, 处理本次数据
if (buffer.length() != 0) {
Log.d("main", "发送数据");
sendBufferData();
} else {
Log.d("main", "数据为空, 放弃发送数据");
}
}
}
}, intervalTime, intervalTime);
直接初始化一个Toast或方法, 多页面共用
public static Toast toast = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (toast == null) {
toast = Toast.makeText(MainActivity.this, "", Toast.LENGTH_SHORT);
}
}