概述
最近在做一个项目,该项目需要通过JNI 在C 层加载dlopen 一个.so 文件,然而执行该.so 的函数时会由于不确定的原因导致手机系统重启(注意是整个手机重启,不是App 挂了)。现在有一个需求:在系统崩溃之前记录一个flag,如果执行没有崩溃就清除这个flag;否则等下次手机重启后再次执行前检查该flag,以此来判断手机是否重启过。
让人抓狂的是试过很多方法,这个flag 总是记录不下来,手机一崩溃重启数据就丢失了。
1. 在/data/data/包名/file/... 目录下创建文件,将flag写入到文件write,flush,close
结果:可能是由于linux 文件系统的cache 机制,尽管flush 了,当手机重启后读该文件却是null,没有写入任何内容。甚至尝试过两次open,write,flush,都没有用。
2. 在/data/local/tmp 目录下创建文件,将flag写入到文件write,flush,close
结果:Permission denied,没有权限在该目录下创建文件
3. SystemProperties.set(“persist.”);
结果:Android系统没有SystemProperties 函数,只能通过反射写属性。但是带 “persist.”的属性普通user 无权限
4. SharePreferences
结果:尝试用SharePreferences来存储flag,仍然失败,当手机重启后读不到该flag
5. 直接写数据库SQLiteDatabase
结果:成功写入,当手机重启后能够读到该flag,欣喜若狂。不明其理,反正测试每次都可以正确保存,问题解决!
写入示例代码:
SQLiteDatabase database = DatabaseHelper.getInstance(context).getWritableDatabase();
try {
if (database != null) {
ContentValues value = new ContentValues();
value.put(DatabaseHelper.REBOOT_CRASH_COLUMN, "");
database.update(DatabaseHelper.DATABASE_TABLE_NAME, value, null, null);
}
} catch (Exception e) {
//TODO
}
if (database != null) {
database.close();
}
SQLiteDatabase database = DatabaseHelper.getInstance(context).getWritableDatabase();
String crashInfo = null;
Cursor cursor = null;
try {
if (database != null) {
String[] columns = { column };
cursor = database.query(DatabaseHelper.DATABASE_TABLE_NAME, columns, null, null, null, null, null);
if (null != cursor && cursor.getCount() > 0) {
cursor.moveToFirst();
do {
crashInfo = cursor.getString(cursor.getColumnIndex(column));
} while(cursor.move(1));
}
}
} catch (Exception e) {
//TODO
}
if (cursor != null) {
cursor.close();
}
if (database != null) {
database.close();
}
问题补充:
最近和同事又讨论起这个问题,找到另一个解决办法。其实文件 open、write完之后,调用一下sync()函数,就可以实时将数据写到磁盘的文件系统上(flush 函数并不能实时写磁盘,这一点要注意)!
private boolean writeFile(File targetFile) {
FileOutputStream out = null;
try {
out = new FileOutputStream(targetFile);
byte[] temp = new byte[]{‘a’,’b’,’c’,’d’,’e’};
out.write(temp, 0, 5);
if (out != null) {
out.getFD().sync();
out.close();
}
return true;
} catch (Exception e) {
if (out != null) {
try {
out.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
return false;
}
}
在C层同样也可以调用fsync()函数:
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
const char* journal_filename = “journal.log”;
void write_journal_entry (char* entry)
{
int fd = open (journal_filename, O_WRONLY | O_CREAT | O_APPEND, 0660);
write (fd, entry, strlen (entry));
write (fd, “n”, 1);
fsync (fd);
close (fd);
}
最后
以上就是缥缈外套为你收集整理的Android 打开文件后向文件写数据,但数据并不能实时保存到磁盘的全部内容,希望文章能够帮你解决Android 打开文件后向文件写数据,但数据并不能实时保存到磁盘所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复