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

前言

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

对跨进程调用感兴趣的同学,可以参阅另一篇文章《跨进程的EventBus,开源框架HermesEventBus使用小结》介绍了一种基于AIDL的跨进程开源框架的使用。

跨进程的SharedPreference——Tray

项目地址:https://github.com/grandcentrix/tray

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

This constant was deprecated in API level 23.MODE_MULTI_PROCESS does not work reliably in some versions of Android, and furthermore does not provide any mechanism for reconciling concurrent modifications across processes. Applications should not attempt to use it. Instead, they should use an explicit cross-process data management approach such as ContentProvider.

至于之前能否保证跨进程安全,好像也是不太可靠的。所以建议使用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

项目地址:https://github.com/TimotheeJeannin/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

项目地址:https://github.com/sqlcipher/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());
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容