首页 > 代码库 > 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的目录。