自定义ContentProvider实现跨进程数据共享

最近要开发一个跨进程数据共享的功能,要实现这个功能,我脑海里第一个想到的是用SharedPreferences,但是发现在Android 7.0以上的版本Context.MODE_WORLD_READABLE属性已经废除,不能用了,所以放弃使用SharedPreferences来实现了。最终决定使用ContentProvider结合SharedPreferences来实现这个功能,话不多说,上代码

1、在你要进行数据共享的应用程序【A程序】中新建CustomProvider类

package com.hades.toolkit.utils;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.Iterator;

/**
 * ContentProvider跨进程数据共享
 *
 * @author Hades
 * @date 2021/8/30.
 */
public class CustomProvider extends ContentProvider {

    public static final Uri AUTHORITY_URI = Uri.parse("content://com.carshow.provider");//此处可以将com.carshow.provider换成你们自己的包名
    public static final Uri CONTENT_URI = AUTHORITY_URI;

    public static final String PARAM_KEY = "key";

    public static final String PARAM_VALUE = "value";

    private final String DB_NAME = "ToolkitProviderData";
    private SharedPreferences mStore;

    public static Cursor query(Context context, String... keys) {
        return context.getContentResolver().query(CONTENT_URI, keys, null, null, null);
    }

    public static String getString(Context context, String key) {
        return getString(context, key, null);
    }

    public static String getString(Context context, String key, String defValue) {
        Cursor cursor = query(context, key);
        String ret = defValue;
        if (cursor.moveToNext()) {
            ret = cursor.getString(0);
            if (TextUtils.isEmpty(ret)) {
                ret = defValue;
            }
        }
        cursor.close();
        return ret;
    }

    public static int getInt(Context context, String key, int defValue) {
        Cursor cursor = query(context, key);
        int ret = defValue;
        if (cursor.moveToNext()) {
            try {
                ret = cursor.getInt(0);
            } catch (Exception e) {

            }
        }
        cursor.close();
        return ret;
    }

    public static Uri save(Context context, ContentValues values) {
        return context.getContentResolver().insert(GlobalProvider.CONTENT_URI, values);
    }

    public static Uri save(Context context, String key, String value) {
        ContentValues values = new ContentValues(1);
        values.put(key, value);
        return save(context, values);
    }

    public static Uri save(Context context, String key, int value) {
        ContentValues values = new ContentValues(1);
        values.put(key, value);
        return save(context, values);
    }

    public static Uri remove(Context context, String key) {
        return save(context, key, null);
    }

    @Override
    public boolean onCreate() {
        mStore = getContext().getSharedPreferences(DB_NAME, Context.MODE_PRIVATE);
        return true;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        int size = projection == null ? 0 : projection.length;
        if (size > 0) {
            String[] values = new String[size];
            for (int i = 0; i < size; i++) {
                values[i] = getValue(projection[i], null);
            }
            return createCursor(projection, values);
        }
        String key = uri.getQueryParameter(PARAM_KEY);
        String value = null;
        if (!TextUtils.isEmpty(key)) {
            value = getValue(key, null);
        }
        return createSingleCursor(key, value);
    }

    protected Cursor createSingleCursor(String key, String value) {
        MatrixCursor cursor = new MatrixCursor(new String[]{key}, 1);
        if (!TextUtils.isEmpty(value)) {
            cursor.addRow(new Object[]{value});
        }
        return cursor;
    }

    protected Cursor createCursor(String[] keys, String[] values) {
        MatrixCursor cursor = new MatrixCursor(keys, 1);
        cursor.addRow(values);
        return cursor;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        return "";
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        if (values != null && values.size() > 0) {
            save(values);
        } else {
            String key = uri.getQueryParameter(PARAM_KEY);
            String value = uri.getQueryParameter(PARAM_VALUE);
            if (!TextUtils.isEmpty(key)) {
                save(key, value);
            }
        }
        return null;
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        String key = selection == null ? selection : uri.getQueryParameter(PARAM_KEY);
        if (!TextUtils.isEmpty(key)) {
            remove(key);
            return 1;
        }
        return 0;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        if (values != null && values.size() > 0) {
            save(values);
            return values.size();
        }
        String key = uri.getQueryParameter(PARAM_KEY);
        String value = uri.getQueryParameter(PARAM_VALUE);
        if (!TextUtils.isEmpty(key)) {
            save(key, value);
            return 1;
        }
        return 0;
    }

    protected String getValue(String key, String defValue) {
        return mStore.getString(key, defValue);
    }

    protected void save(ContentValues values) {
        String key;
        String value;
        Iterator<String> iterator = values.keySet().iterator();
        SharedPreferences.Editor editor = mStore.edit();
        while (iterator.hasNext()) {
            key = iterator.next();
            value = values.getAsString(key);
            if (!TextUtils.isEmpty(key)) {
                if (value != null) {
                    editor.putString(key, value);
                } else {
                    editor.remove(key);
                }
            }
        }
        editor.commit();
    }

    protected void save(String key, String value) {
        SharedPreferences.Editor editor = mStore.edit();
        if (value != null) {
            editor.putString(key, value);
        } else {
            editor.remove(key);
        }
        editor.commit();
    }

    protected void remove(String key) {
        SharedPreferences.Editor editor = mStore.edit();
        editor.remove(key);
        editor.commit();
    }

}

2、在【A程序】的注册清单中<application>内添加provider属性

<provider
    android:exported = "true"
    android:authorities = "com.carshow.provider"//此处一定要和前面添加的CustomProvider类中设置的URI名字一致
    android:name = "com.hades.toolkit.utils.CustomProvider"/>

3、在需要调用其他应用共享数据的程序中【B程序】也添加上述CustomProvider类,但不需要在注册清单中添加provider属性,记住,两个程序中的CustomProvider类中AUTHORITY_URI 参数的包名一定要一致,可以将类直接从【A程序】中复制到【B程序】中,不用更改任何参数

4、完成上述操作后可直接使用

        在【A程序】中存储数据:

CustomProvider.save(this, "RightFront", 6);//第一个参数是Context,第二个参数是Key,第三个参数是要保存的值,值的类型我在上面CustomProvider类中只添加了String和int两种类型,也可以根据需求新建方法。

        在【B程序】中读取数据:

int vaue = CustomProvider.getInt(this, "RightFront", 0);//第三个参数是默认值

完成!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
简明、完整、全面的安卓开发demo集合,包含如下示例 1、LinearLayout Button、RadioGroup、 CheckBox 2、TableLayout 3、FrameLayout 霓虹灯效果 4、RelativeLayout 梅花效果 5、自定义view跟着触点走的小球 6、 ListView 列表视图 7、WebView web视图 8、ToggleButton 动态布局效果 9、AnalogClock 、 DigitalClock and Chronometer 时钟和数字日期 10、AutoCompleteTextView 根据输入自动补充可能的全部 11、Spinner View 选择框(弹出框形式选择) 12、DatePicker TimePicker View 日期时间选择器 13、ProgressBar View 普通进度条、显示在标题栏上的进度条 14、RatingBar View 评级 15、 SeekBar 拖动条,音量调节效果 16、ScrollView 、HorizontalScrollView 垂直和水平滚动条 17、ScrollView 、HorizontalScrollView 垂直和水平滚动条 18、ExpandableListView 分组可展开收缩的ListView 19、Notification 状态栏通知 20、GridView、ImageSwitcher 21、SmsManager 消息管理器,发短信(这里是模拟器只能给其它模拟器发短信) 22、Intent Action、Category属性 测试 23、系统 Action、Category属性 24、ClipDrawable 徐徐展开的风景 25、AnimationDrawable 会动的图片 26、Menu、SubMenu、ContextMenu xml配置menu 27、Attribute 自定义view的duration属性 控制图片的透明度 28、Bitmap、BitmapFactory 图形与图像处理 29、Canvas 绘制自定义图形 30、Canvas 采用双缓存实现画图板 31、SharedPreference 简单的key-value数据存取 32、SQLiteDatabase 安卓客户端的嵌入式数据库 33、GestureDetector + ViewFlipper实现翻页效果 34、GestureLiberay 自定义手势 35、GestureLiberay 通过自定义的手势实现用户操作 36、TextToSpeech 语音朗读 37、ContentProviderContentResolver 应用之间共享数据 38、 Service 相当于没有界面的activity 39、Activity与Service运行中通信 40、Service 相当于没有界面的activity 41、AIDL Service android中的进程调用 客户端,服务端见AidlService 42、BroadcastReceiver 接收广播消息 43、非UI线程中不能操作UI线程中的View测试 44、ImageSwitcher animation gesture实现可以滑动的跑马灯 45、下载状态栏显示下载进度 46、Gallery3d效果 47、ListView 上拉加载更多效果 48、异步加载图片的二级缓存技术 49、QQ的好友列表展示效果 50、Fragment + ViewPager实现tab滑动切换 51、能够显示在桌面前面的的歌词效果 52、activity切换特效
初学者必看 1、LinearLayout Button、RadioGroup、 CheckBox 2、TableLayout 3、FrameLayout 霓虹灯效果 4、RelativeLayout 梅花效果 5、自定义view跟着触点走的小球 6、 ListView 列表视图 7、WebView web视图 8、ToggleButton 动态布局效果 9、AnalogClock 、 DigitalClock and Chronometer 时钟和数字日期 10、AutoCompleteTextView 根据输入自动补充可能的全部 11、Spinner View 选择框(弹出框形式选择) 12、DatePicker TimePicker View 日期时间选择器 13、ProgressBar View 普通进度条、显示在标题栏上的进度条 14、RatingBar View 评级 15、 SeekBar 拖动条,音量调节效果 16、ScrollView 、HorizontalScrollView 垂直和水平滚动条 17、ScrollView 、HorizontalScrollView 垂直和水平滚动条 18、ExpandableListView 分组可展开收缩的ListView 19、Notification 状态栏通知 20、GridView、ImageSwitcher 21、SmsManager 消息管理器,发短信(这里是模拟器只能给其它模拟器发短信) 22、Intent Action、Category属性 测试 23、系统 Action、Category属性 24、ClipDrawable 徐徐展开的风景 25、AnimationDrawable 会动的图片 26、Menu、SubMenu、ContextMenu xml配置menu 27、Attribute 自定义view的duration属性 控制图片的透明度 28、Bitmap、BitmapFactory 图形与图像处理 29、Canvas 绘制自定义图形 30、Canvas 采用双缓存实现画图板 31、SharedPreference 简单的key-value数据存取 32、SQLiteDatabase 安卓客户端的嵌入式数据库 33、GestureDetector + ViewFlipper实现翻页效果 34、GestureLiberay 自定义手势 35、GestureLiberay 通过自定义的手势实现用户操作 36、TextToSpeech 语音朗读 37、ContentProviderContentResolver 应用之间共享数据 38、 Service 相当于没有界面的activity 39、Activity与Service运行中通信 40、Service 相当于没有界面的activity 41、AIDL Service android中的进程调用 客户端,服务端见AidlService 42、BroadcastReceiver 接收广播消息 43、非UI线程中不能操作UI线程中的View测试 44、ImageSwitcher animation gesture实现可以滑动的跑马灯 45、下载状态栏显示下载进度 46、Gallery3d效果 47、ListView 上拉加载更多效果 48、异步加载图片的二级缓存技术 49、QQ的好友列表展示效果 50、Fragment + ViewPager实现tab滑动切换 51、能够显示在桌面前面的的歌词效果 52、activity切换特效
Android开发艺术探索》是一本Android进阶类书籍,采用理论、源码和实践相结合的方式来阐述高水准的Android应用开发要点。《Android开发艺术探索》从三个方面来组织内容。第一,介绍Android开发者不容易掌握的一些知识点;第二,结合Android源代码和应用层开发过程,融会贯通,介绍一些比较深入的知识点;第三,介绍一些核心技术和Android的性能优化思想。 《Android开发艺术探索》侧重于Android知识的体系化和系统工作机制的分析,通过《Android开发艺术探索》的学习可以极大地提高开发者的Android技术水平,从而更加高效地成为高级开发者。而对于高级开发者来说,仍然可以从《Android开发艺术探索》的知识体系中获益。 全书目录 ------------------------------------------------------------------- 第1章 Activity的生命周期和启动模式 / 1   1.1 Activity的生命周期全面分析 / 1   1.1.1 典型情况下的生命周期分析 / 2   1.1.2 异常情况下的生命周期分析 / 8   1.2 Activity的启动模式 / 16   1.2.1 Activity的LaunchMode / 16   1.2.2 Activity的Flags / 27   1.3 IntentFilter的匹配规则 / 28   第2章 IPC机制 / 35   2.1 Android IPC简介 / 35   2.2 Android中的多进程模式 / 36   2.2.1 开启多进程模式 / 36   2.2.2 多进程模式的运行机制 / 39   2.3 IPC基础概念介绍 / 42   2.3.1 Serializable接口 / 42   2.3.2 Parcelable接口 / 45   2.3.3 Binder / 47   2.4 Android中的IPC方式 / 61   2.4.1 使用Bundle / 61   2.4.2 使用文件共享 / 62   2.4.3 使用Messenger / 65   2.4.4 使用AIDL / 71   2.4.5 使用ContentProvider / 91   2.4.6 使用Socket / 103   2.5 Binder连接池 / 112   2.6 选用合适的IPC方式 / 121   第3章 View的事件体系 / 122   3.1 View基础知识 / 122   3.1.1 什么是View / 123   3.1.2 View的位置参数 / 123   3.1.3 MotionEvent和TouchSlop / 125   3.1.4 VelocityTracker、GestureDetector和Scroller / 126   3.2 View的滑动 / 129   3.2.1 使用scrollTo/scrollBy / 129   3.2.2 使用动画 / 131   3.2.3 改变布局参数 / 133   3.2.4 各种滑动方式的对比 / 133   3.3 弹性滑动 / 135   3.3.1 使用Scroller / 136   3.3.2 通过动画 / 138   3.3.3 使用延时策略 / 139   3.4 View的事件分发机制 / 140   3.4.1 点击事件的传递规则 / 140   3.4.2 事件分发的源码解析 / 144   3.5 View的滑动冲突 / 154   3.5.1 常见的滑动冲突场景 / 155   3.5.2 滑动冲突的处理规则 / 156   3.5.3 滑动冲突的解决方式 / 157   第4章 View的工作原理 / 174   4.1 初识ViewRoot和DecorView / 174   4.2 理解MeasureSpec / 177   4.2.1 MeasureSpec / 177   4.2.2 MeasureSpec和LayoutParams的对应关系 / 178   4.3 View的工作流程 / 183   4.3.1 measure过程 / 183   4.3.2 layout过程 / 193   4.3.3 draw过程 / 197   4.4 自定义View / 199   4.4.1 自定义View的分类 / 200   4.4.2 自定义View须知 / 201   4.4.3 自定义View示例 / 202   4.4.4 自定义View的思想 / 217   第5章 理解RemoteViews / 218   5.1 RemoteViews的应用 / 218   5.1.1 RemoteViews在通知栏上的应用 / 219   5.1.2 RemoteViews在桌面小部件上的应用 / 221   5.1.3 PendingIntent概述 / 228   5.2 RemoteViews的内部机制 / 230   5.3 RemoteViews的意义 / 239   第6章 Android的Drawable / 243   6.1 Drawable简介 / 243   6.2 Drawable的分类 / 244   6.2.1 BitmapDrawable / 244   6.2.2 ShapeDrawable / 247   6.2.3 LayerDrawable / 251   6.2.4 StateListDrawable / 253   6.2.5 LevelListDrawable / 255   6.2.6 TransitionDrawable / 256   6.2.7 InsetDrawable / 257   6.2.8 ScaleDrawable / 258   6.2.9 ClipDrawable / 260   6.3 自定义Drawable / 262   第7章 Android动画深入分析 / 265   7.1 View动画 / 265   7.1.1 View动画的种类 / 265   7.1.2 自定义View动画 / 270   7.1.3 帧动画 / 272   7.2 View动画的特殊使用场景 / 273   7.2.1 LayoutAnimation / 273   7.2.2 Activity的切换效果 / 275   7.3 属性动画 / 276   7.3.1 使用属性动画 / 276   7.3.2 理解插值器和估值器 / 280   7.3.3 属性动画的监听器 / 282   7.3.4 对任意属性做动画 / 282   7.3.5 属性动画的工作原理 / 288   7.4 使用动画的注意事项 / 292   第8章 理解Window和WindowManager / 294   8.1 Window和WindowManager / 294   8.2 Window的内部机制 / 297   8.2.1 Window的添加过程 / 298   8.2.2 Window的删除过程 / 301   8.2.3 Window的更新过程 / 303   8.3 Window的创建过程 / 304   8.3.1 Activity的Window创建过程 / 304   8.3.2 Dialog的Window创建过程 / 308   8.3.3 Toast的Window创建过程 / 311   第9章 四大组件的工作过程 / 316   9.1 四大组件的运行状态 / 316   9.2 Activity的工作过程 / 318   9.3 Service的工作过程 / 336   9.3.1 Service的启动过程 / 336   9.3.2 Service的绑定过程 / 344   9.4 BroadcastReceiver的工作过程 / 352   9.4.1 广播的注册过程 / 353   9.4.2 广播的发送和接收过程 / 356   9.5 ContentProvider的工作过程 / 362   第10章 Android的消息机制 / 372   10.1 Android的消息机制概述 / 373   10.2 Android的消息机制分析 / 375   10.2.1 ThreadLocal的工作原理 / 375   10.2.2 消息队列的工作原理 / 380   10.2.3 Looper的工作原理 / 383   10.2.4 Handler的工作原理 / 385   10.3 主线程的消息循环 / 389   第11章 Android的线程和线程池 / 391   11.1 主线程和子线程 / 392   11.2 Android中的线程形态 / 392   11.2.1 AsyncTask / 392   11.2.2 AsyncTask的工作原理 / 395   11.2.3 HandlerThread / 402   11.2.4 IntentService / 403   11.3 Android中的线程池 / 406   11.3.1 ThreadPoolExecutor / 407   11.3.2 线程池的分类 / 410   第12章 Bitmap的加载和Cache / 413   12.1 Bitmap的高效加载 / 414   12.2 Android中的缓存策略 / 417   12.2.1 LruCache / 418   12.2.2 DiskLruCache / 419   12.2.3 ImageLoader的实现 / 424   12.3 ImageLoader的使用 / 441   12.3.1 照片墙效果 / 441   12.3.2 优化列表的卡顿现象 / 446   第13章 综合技术 / 448   13.1 使用CrashHandler来获取应用的crash信息 / 449   13.2 使用multidex来解决方法数越界 / 455   13.3 Android的动态加载技术 / 463   13.4 反编译初步 / 469   13.4.1 使用dex2jar和jd-gui反编译apk / 470   13.4.2 使用apktool对apk进行二次打包 / 470   第14章 JNI和NDK编程 / 473   14.1 JNI的开发流程 / 474   14.2 NDK的开发流程 / 478   14.3 JNI的数据类型和类型签名 / 484   14.4 JNI调用Java方法的流程 / 486   第15章 Android性能优化 / 489   15.1 Android的性能优化方法 / 490   15.1.1 布局优化 / 490   15.1.2 绘制优化 / 493   15.1.3 内存泄露优化 / 493   15.1.4 响应速度优化和ANR日志分析 / 496   15.1.5 ListView和Bitmap优化 / 501   15.1.6 线程优化 / 501   15.1.7 一些性能优化建议 / 501   15.2 内存泄露分析之MAT工具 / 502   15.3 提高程序的可维护性 / 506
视频名称 源码 -------------------------------------------------------------------------------- 04_开发与运行(卸载)第一个ANDROID应用.avi 所在项目:Hello 06_电话拔号器.avi 所在项目:phone 08_短信发送器.avi 所在项目:sms 09_深入了解各种布局技术.avi 所在项目:sms & FrameLayout 10_对应用进行单元测试.avi 所在项目:junitest 11_查看与输出日志信息.avi 所在项目:junitest 12_文件的保存与读取.avi 所在项目:File 13_文件的操作模式.avi 所在项目:File & other 14_把文件存放在SDCard.avi 所在项目:File 15_采用Pull解析器解析和生成XML内容.avi 所在项目:xml 16_采用SharedPreferences保存用户偏好设置参数.avi 所在项目:SharedPreferences 17_创建数据库与完成数据添删改查.avi 所在项目:db 18_在SQLite中使用事务.avi 所在项目:db 19_采用ListView实现数据列表显示.avi 所在项目:db 20_采用ContentProvider对外共享数据.avi 所在项目:db & other 21_监听ContentProvider中数据的变化.avi 所在项目:db & other & Aapp 22_访问通信录中的联系人和添加联系人.avi 所在项目:contacts 23_网络通信之网络图片查看器.avi 所在项目:netimage & Web端应用:web 24_网络通信之网页源码查看器.avi 所在项目:HtmlViewer & Web端应用:web 25_网络通信之视频资讯客户端.avi 所在项目:news & Web端应用:web 26_采用JSON格式返回数据给资讯客户端.avi 所在项目:news & Web端应用:web 27_网络通信之通过GET和POST方式提交参数给web应用.avi 所在项目:newsmanage & Web端应用:web 28_网络通信之通过HTTP协议实现文件上传.avi 所在项目:newsmanage & Web端应用:web 29_发送xml数据和调用webservice.avi 所在项目:mobileAddressQuery & Web端应用:web 30_多线程下载原理.avi 所在项目:net 31_多线程断点下载器.avi 所在项目:MulThreadDownloader 32_文件断点上传器.avi 所在项目:videoUpload & javaSE应用:socket 33_为应用添加多个Activity与参数传递.avi 所在项目:MulActivity 34_Activity的启动模式.avi 所在项目:LaunchMode & openSingleInstance & singleInstance 35_Intent深入解剖.avi 所在项目:Intent 36_Activity生命周期.avi 所在项目:ActivityLife 37_采用广播接收者实现短信窃听器.avi 所在项目:SMSListener & Web端应用:web 38_采用广播接收者拦截外拔电话与其特性.avi 所在项目:SMSListener 39_采用Service实现电话窃听器.avi 所在项目:phonelistener 40_建立能与访问者进行相互通信的本地服务.avi 所在项目:studentquery 41_使用AIDL实现进程通信.avi 所在项目:remoteService & remoteServiceClient 42_服务的生命周期.avi 43_音乐播放器.avi 所在项目:audioplayer 44_在线视频播放器.avi 所在项目:videoplayer 45_拍照.avi 所在项目:takepicture 46_视频刻录.avi 所在项目:videoRecorder 47_手势识别.avi 所在项目:gesture & GestureBuilder 48_实现软件国际化.avi 所在项目:i18n 49_屏幕适配.avi 所在项目:ScreenAdapter 50_样式与主题.avi 所在项目:style 51_编码实现软件界面.avi 所在项目:codeUI 52_发送状态栏通知.avi 所在项目:Notification 53_采用网页设计软件界面.avi 所在项目:htmlUI 54_tween动画.avi 所在项目:tween 55_frame动画的实现.avi 所在项目:frameAnimation 56_activity切换动画与页面切换动画.avi 所在项目:animation 57_采用方向传感器实现指南针.avi 所在项目:sensor 58_拖拉功能与多点触摸.avi 所在项目:DragScale 59_各种图形的使用介绍.avi 所在项目:drawable 60_meta-data的使用.avi 所在项目:metadata 61_Widget.avi 所在项目:Widgets 62_自定义窗口标题.avi 所在项目:customtitle 63_PopupWindow.avi 所在项目:PopupWindow 64_ListView数据异步加载与AsyncTask.avi 所在项目:DataAsyncLoad 65_ListView数据的分批加载.avi 所在项目:datapageload 66_自定义标签页.avi 所在项目:tabhost 67_TraceView性能测试与Android应用性能优化方案.avi 所在项目:tabhost Android核心基础加强内容(暂不对外公布) 复杂UI界面设计、GPS与GoogleMap、自定义View、Ubuntu Linux下使用C语言面向底层开发、通过JNI进行底层组件调用、图形与OpenGl ES、界面特效、下载修改及编绎Android框架代码。
当然可以!以下是在Android Studio中使用自定义ContentProvider实现共享生词本的步骤: 1. 首先,在Android Studio中创建一个新项目。 2. 在项目的build.gradle文件中添加以下依赖项: ```groovy implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.core:core-ktx:1.3.2' ``` 3. 在AndroidManifest.xml文件中添加以下权限声明: ```xml <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ``` 4. 在AndroidManifest.xml文件中添加以下内容提供者声明: ```xml <provider android:name=".MyContentProvider" android:authorities="com.example.myapp.MyContentProvider" android:exported="true" /> ``` 注意:android:authorities是一个唯一标识符,应该根据您的应用程序进行更改。 5. 在项目中创建一个新的Java类,名为MyContentProvider,并继承ContentProvider类。在该类中,您需要实现以下方法: ```java @Override public boolean onCreate() { // 初始化您的ContentProvider return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // 查询数据并返回Cursor对象 return null; } @Override public String getType(Uri uri) { // 返回数据的MIME类型 return null; } @Override public Uri insert(Uri uri, ContentValues values) { // 插入数据并返回新数据的Uri return null; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // 删除数据并返回受影响的行数 return 0; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // 更新数据并返回受影响的行数 return 0; } ``` 6. 在MyContentProvider类中,您可以使用以下代码获取共享的生词本数据: ```java String filePath = Environment.getExternalStorageDirectory().getPath() + "/myWordList.txt"; File file = new File(filePath); FileInputStream inputStream = new FileInputStream(file); byte[] buffer = new byte[inputStream.available()]; inputStream.read(buffer); String text = new String(buffer); ``` 7. 最后,您可以在应用程序中使用以下代码访问MyContentProvider: ```java String[] projection = { "word", "definition" }; Uri uri = Uri.parse("content://com.example.myapp.MyContentProvider/words"); Cursor cursor = getContentResolver().query(uri, projection, null, null, null); ``` 请注意:在使用ContentProvider时,应该使用ContentResolver类来访问数据。通过调用getContentResolver()方法获取ContentResolver对象,然后使用该对象来访问ContentProvider

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

仗剑走天涯~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值