Android - Content Provider

ContentProvider在android中的作用是对外共享应用的私有数据,也就是说可以通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentProvider对应用中的数据进行添删改查。

关于数据共享,前面的文件操作模式中知道通过指定文件的操作模式为Context.MODE_WORLD_READABLE或Context.MODE_WORLD_WRITEABLE同样也可以对外共享数据。

那么,为何还要使用ContentProvider 对外共享数据呢?
如果采用文件操作模式对外共享数据,数据的访问方式会因数据存储的方式不同而不同,导致数据的访问方式无法统一,
如:采用xml文件对外共享数据,需要进行xml解析才能读取数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读取数据等等。

使用ContentProvider对外共享数据的好处是统一了数据的访问方式

成为ContentProvider

当应用需要通过ContentProvider对外共享数据时,第一步需要继承ContentProvider并重写下面方法:

ContentProvider - PersonContentProvider.java
1
2
3
4
5
6
7
8
public class PersonContentProvider extends ContentProvider{
public boolean onCreate(){}
public Uri insert(Uri uri, ContentValues values){}
public int delete(Uri uri, String selection, String[] selectionArgs){}
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs){}
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder){}
public String getType(Uri uri){}
}

第二步需要在AndroidManifest.xml 的<provider>节点对该ContentProvider进行配置,为了能让其他应用找到该ContentProvider,ContentProvider 采用了authority(主机名/域名)对它进行唯一标识(详见Content URIs)

Manifest - AndroidManifest.xml
1
2
3
4
5
<manifest .... >
<application android:icon="@drawable/icon" android:label="@string/app_name">
<provider android:name=".PersonContentProvider" android:authorities="net.yrom.providers.personprovider"/>
</application>
</manifest>

Tips:Content Provider在<provider>节点中也可以声明一些访问的权限,当访问者没有申请到权限是不能访问provider的。

ContentProvider类主要方法

  • boolean onCreate()
    该方法在ContentProvider创建后就会被调用, Android开机后, ContentProvider在其它应用第一次访问它时才会被创建。
  • Uri insert(Uri uri, ContentValues values)
    该方法用于供外部应用往ContentProvider添加数据。
  • int delete(Uri uri, String selection, String[] selectionArgs)
    该方法用于供外部应用从ContentProvider删除数据。
  • int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
    该方法用于供外部应用更新ContentProvider中的数据。
  • Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
    该方法用于供外部应用从ContentProvider中获取数据。
  • String getType(Uri uri)
    该方法用于返回当前Url所代表数据的MIME类型。

如果操作的数据属于集合类型,那么MIME类型字符串应该以vnd.android.cursor.dir/开头。
例如:要得到所有person记录的Uri为content://net.yrom.provider.personprovider/person,那么返回的MIME类型字符串应该为:“vnd.android.cursor.dir/person”。

如果要操作的数据属于非集合类型数据,那么MIME类型字符串应该以vnd.android.cursor.item/开头。
例如:得到id为10的person记录,Uri为content://net.yrom.provider.personprovider/person/10,那么返回的MIME类型字符串应该为:“vnd.android.cursor.item/person”。

Android - 数据的存储

Android中的数据存储有以下几种方式:

  1. 文件存储
  2. SharedPreferences
  3. SQLite数据库
  4. Content Provider

文件存储

Activity中的openFileOutput()方法可以用于把数据输出到文件中,具体的实现过程与在JavaSE 环境中保存数据到文件中是一样的。
openFileInput()方法则用于读取当前应用的保存的数据

openFileOutpupt详解

openFileOutput(String name, int mode)
name - 指定文件名称,不能包含路径分隔符“/” ,如果文件不存在,Android 会自动创建它。创建的文件保存在/data/data//files目录,如: /data/data/net.yrom.xxx/files/xxx.txt
mode - 文件操作模式,即访问权限

0 或者MODE_PRIVATE 默认的模式,文件为私有的,只能本应用程序才能访问;
MODE_APPEND 添加默认,数据将追加到文件末尾;
MODE_WORLD_READABLE 全局可读;!危险
MODE_WORLD_WRITEABLE 全局可写。!危险

eg.

1
2
3
4
5
6
7
8
9
public class FileActivity extends Activity {
//...
public void save2File(byte[] data, String filename) {
//...
FileOutputStream out = this.openFileOutput(filename, Context.MODE_PRIVATE);
out.write( data);
out.close();
}
}

获得应用的文件存储路径

getFileDir() - /data/data/<当前应用包名>/files/
getCacheDir() - /data/data/<当前应用包名>/cache/
Environment.getExternalStorageDirectory() - 用于获取SDCard的目录,
注意:

  1. 写数据应在程序清单文件中加入sdcard的访问权限:
    android.permission.WRITE_EXTERNAL_STORAGE
  2. 先判断sdcard是否挂载:
    Environment.getExternalStorageState() 应返回 Environment.MEDIA_MOUNTED
    eg.获取sdcard的可用大小:
    1
    2
    3
    4
    5
    6
    7
    8
    if(Environment.getExternalStorageState().equals(Environment. MEDIA_MOUNTED)){
    File sd = Environment. getExternalStorageDirectory();
    StatFs stat = new StatFs(sd.getPath());
    long availableBlocks = stat.getAvailableBlocks();
    long blockSize = stat.getBlockSize();
    long availableSize = availableBlocks * blockSize;
    String totalAvailableSize = Formatter.formatFileSize(getApplicationContext(), availableSize);
    }

    SharedPreferences

    Android应用一般采用SharedPreferences来存储于应用相关的配置参数
    其实就是 /data/data/<package name>/shared_prefs/ 目录下的xml文件

Android - Activity

Android组件:Activity、Service、Broadcast Receiver、Content Provider

Activity

Android中的Activity有四个基本状态:

  1. Actived/Runing 一个新的Activity被启动,处于Activity任务栈栈顶,显示在屏幕最前端,此时它处于可见并可和用户交互的激活状态。
  2. Paused 被另一个透明或者 Dialog 样式的 Activity 覆盖时的状态。仍然可见,但已失去焦点,不能与用户交互
  3. Stoped 被另一个Activity覆盖、不可见、失去焦点的状态。
  4. Killed/Destoryed 被系统回收,Activity实例被销毁

这些状态之间转换都依赖于用户的操作。程序员可以决定一个Activity何时启动,但不能决定它何时被销毁。

Activity生命周期方法

在android.app.Activity类中定义了一系列生命周期相关的方法,在应用自定义的Activity中只要复写了这些方法中所需的,就可以确保被android系统调用到。
Activity生命周期