首页 > 代码库 > cpe移植到framework后,原有数据库存放问题的解决。
cpe移植到framework后,原有数据库存放问题的解决。
最近公司业务需要,把原以apk形式存在的CPE,打入framework层,即剥离出cpe,搞了好半天,终于有时间写博客,做个笔记把遇到的问题说下。
首先遇到的问题是原apk中的一些东西,移植到framework层后,环境不同,必须做一些修改。
例如,
1.ContentProvider,因没有提供给其他程序数据共享,要么去掉,全部改为sqlite直接调用。要么把这个ContentProvider剥离出来,形成一个apk,固定到framework,给cpe提供ContentProvider.
2.SharedPreferences,打入framework后,SharedPreferences没有地方存放由它生成的xml文件,因此也要去掉,去掉后如何保存它要保存的数据呢,例如终端启动信息和初始化信息等。最终确定使用一个文件来保存,依赖于Properties这个工具类读写数据,Properties最初还遇到了写数据的问题,后来还是解决了。主要是 mProperties.setProperty(name,value);只是把数据写入内存,而没有写入到文件,纠结了半天,修改了一下代码,ok了。
try {
os=new FileOutputStream(CONFIGPATH);
mProperties.setProperty(name,value);
mProperties.store(os, null);
} catch (Exception e) {
e.printStackTrace();
} finally{
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
3.CPE原有的配置文件,在framework层后,目录结构不一样,得找个地方存放这些配置文件。修改了引用这些配置文件所在目录,最后统一移植到/system/etc/cpe/目录下。
4.CPE依赖的第三方jar包,CPE打入framework后,其本身就是一个jar形式存在,只不过由SystemService传入Context其他它。那么CPE所依赖的第三方jar包也得进入framework,开始的时候全部导入到framework,编译并运行后,发现板子上另一个apk也引用了我导入的CPE jar,冲突了。为了避免这个问题,决定修改CPE的包名。
5.如同SharedPreferences,apk生成的db文件,默认在/data/data/包名/database/目录下,而打入framework后,db文件得找个地方存放,为了解决这个问题,查找了很多资料,测试了半天,终于实现了,并将db文件存放在/data/cpe/目录下。因为是apk在测试时候,没打入framework,板子上的目录是没有权限写数据的,只能用U盘做测试,写入/sdcard/目录下测试的。说了半天,即指定目录存放db文件。
定义帮助类继承SQLiteOpenHelper:
public class DatabaseHelper extends SQLiteOpenHelper
构造方法:
private static final String PATH ="/sdcard/cpe";
public DatabaseHelper(Context context, String name) {
super(new CustomPathDatabaseContext(context, PATH), name, null, VERSION);
}
注意构造方法中的CustomPathDatabaseContext.java:
public class CustomPathDatabaseContext extends ContextWrapper{
private static final String TAG = CustomPathDatabaseContext.class.getSimpleName();
private String mDirPath;
public CustomPathDatabaseContext(Context base,String name) {
super(base);
mDirPath = name;
}
@Override
public File getDatabasePath(String name) {
File result = new File(mDirPath + File.separator + name);
if (!result.getParentFile().exists())
{
result.getParentFile().mkdirs();
}
return result;
}
@Override
public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory)
{
Log.d(TAG, "openOrCreateDatabase");
return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), factory);
}
@Override
public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory, DatabaseErrorHandler errorHandler){
Log.d(TAG,"openOrCreateDatabase...");
return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name).getAbsolutePath(), factory, errorHandler);
}
}
为什么要这样定义,查看源码,ContextWrapper就是Context的实现类,在getReadableDatabase(),或getWriteableDatabase()调用后,会执行openOrCreateDatabase(),4.0版本后执行第二个openOrCreateDatabase(),这样就指定了db的目录。