搜索
您的当前位置:首页正文

介绍几种Android支持跨进程共享数据的开源框架

来源:二三娱乐

前言

因为将原项目的单进程架构改为多进程架构,引发了不少跨进程调用和跨进程使用共享数据的问题。本篇文章分享几个我在跨进程共享数据时使用的开源框架。

跨进程的SharedPreference——Tray

首先官方已经在API23后废除了SharedPreference的多进程模式:

至于之前能否保证跨进程安全,好像也是不太可靠的。所以建议使用ContentProvider来实现跨进程共享的数据,而在Github上的开源项目** tray ** 底层通过ContentProvider实现了跨进程共享数据的安全性,并且将上层API的使用封装的更像SharedProference。对跨进程SharedPreference有需求的同学不妨尝试使用它。

** gradle 引入项目: **

    implementation 'net.grandcentrix.tray:tray:0.12.0'   //低版本gradle用compile代替implementation 

** 初始化 **

 private AppPreferences appPreferences = new AppPreferences(context);

** 简单使用 **

    boolean put(@NonNull final String key, @Nullable final String value);

    String getString(@NonNull final String key, @Nullable final String defaultValue);

相比SharedPreference去掉了editor(),写入数据更像在用Map,不过只支持String和基本类型。

快速开发ContentProvider——ProviGen

ProviGen提供了注解支持可以帮助我们在运行时自动创建数据库表,并且封装了ContentProvider模块,开发者只要让自己的Provider继承自ProviGenProvider不再需要自己实现insert()、update()、delete()、query()等接口。

** gradle 引入项目: **

        implementation 'com.github.provigen:ProviGen-lib:2.0.+'  //低版本gradle用compile代替implementation 

** 实现自定义Contract:**

public interface ILocalMessage extends ProviGenBaseContract {

        @Column(Column.Type.INTEGER)
        public static final String Id = "id";

        @Column(Column.Type.TEXT)
        public static final String Title = "title";

        @Column(Column.Type.TEXT)
        public static final String Summary = "summary";

        @Column(Column.Type.TEXT)
        public static final String Content ="content";

        @Column(Column.Type.INTEGER)
        public static final String Type = "type";

        @Column(Column.Type.INTEGER)
        public static final String Status = "status";

        @Column(Column.Type.INTEGER)
        public static final String Level = "level";

        @Column(Column.Type.TEXT)
        public static final String Recievetime = "receive_time";

        @Column(Column.Type.INTEGER)
        public static final String Isfocus = "focus";

        @Column(Column.Type.TEXT)
        public static final String Username = "user_name";

        @ContentUri
        public static final Uri CONTENT_URI = Uri.parse("content://xxx.xxx.xxx/message_table");
    }

这个类中需要定义一个数据库表的数据结构,通过注解@Column标记列名变量以及它的类型,通过@ContentUri标记这个数据库表的URI。

** 下一步完善自定义的Provider类:**

public class MessageProvider extends ProviGenProvider {
    private static Class[] messages = new Class[]{ILocalMessage.class};

    @Override
    public SQLiteOpenHelper openHelper(Context context) {
        return new CipherProviGenOpenHelper(getContext(), "message-db", null, 1, messages);
    }

    @Override
    public Class[] contractClasses() {
        return messages;
    }

    @Override
    public boolean onCreate() {
        return super.onCreate();
    }

** 接着只需要在AndroidManifest注册Provider组件 :**

        <provider
            android:name=".provider.MessageProvider"
            android:authorities="xxx.xxx.xxx"
            android:enabled="true"
            android:exported="true"></provider>

下面就可以通过Context.getContentResolver()的增删改成接口跨进程访问数据库了。

加密的SQLite数据库——android-database-sqlcipher

如果在ROOT的手机上运行我们的程序,是可以被轻易拿到SQLite数据库文件的,那么不对数据库加密就显得很不安全的了。android-database-sqlcipher让加密SQLite数据库变得简单。

** 引入项目: **
先编译出so文件,放入到libs文件夹下,然后配置gradle:

android{
    sourceSets{
        main{
            jniLibs.srcDir(['libs'])
        }
    }
}

dependencies {
    implementation files('libs/sqlcipher.jar')
}

** 加载so **

SQLiteDatabase.loadLibs(getContext());

注意这段代码需要在SQlite创建前执行,否则无法获取so提供的api导致程序崩溃。

** 使用方面 **
android-database-sqlcipher提供了net.sqlcipher.database.SQLiteDatabasenet.sqlcipher.database.SQLiteOpenHelper,开发者需要替换掉原生的SQLiteDatabase和SQLiteOpenHelper。

在得到数据库时,需要指定密钥:

 public synchronized SQLiteDatabase getWritableDatabase(String password) {
        return this.getWritableDatabase(password == null?null:password.toCharArray());
}
Top