Android数据存储五种方式使用及总结

转载:http://blog.csdn.net/amazing7/article/details

1、概述

  Android提供了5种方式来让用户保存持久化应用程序数据。根据自己的需求来做选择,比如数据是否是应用程序私有的,是否能被其他程序访问,需要多少数据存储空间等,分别是: 
  
① 使用SharedPreferences存储数据 

② 文件存储数据

③  SQLite数据库存储数据

④ 使用ContentProvider存储数据

⑤ 网络存储数据 

Android提供了一种方式来暴露你的数据(甚至是私有数据)给其他应用程序 - ContentProvider。它是一个可选组件,可公开读写你应用程序数据。

2、SharedPreferences存储

  SharedPreference类提供了一个总体框架,使您可以保存和检索的任何基本数据类型( boolean, float, int, long, string)的持久键-值对(基于XML文件存储的“key-value”键值对数据)。

  通常用来存储程序的一些配置信息。其存储在“data/data/程序包名/shared_prefs目录下。

  xml 处理时Dalvik会通过自带底层的本地XML Parser解析,比如XMLpull方式,这样对于内存资源占用比较好。 

2.1  我们可以通过以下两种方法获取SharedPreferences对象(通过Context):

① getSharedPreferences (String name, int mode)

  当我们有多个SharedPreferences的时候,根据第一个参数name获得相应的SharedPreferences对象。

② getPreferences (int mode)

  如果你的Activity中只需要一个SharedPreferences的时候使用。

这里的mode有四个选项:

<code class="hljs mathematica has-numbering"><span class="hljs-keyword">Context</span>.MODE_PRIVATE</code><ul style="" class="pre-numbering"><li>1</li></ul><ul style="" class="pre-numbering"><li>1</li></ul>

  该SharedPreferences数据只能被本应用程序读、写。

<code class="hljs mathematica has-numbering"><span class="hljs-keyword">Context</span>.MODE_WORLD_READABLE</code><ul style="" class="pre-numbering"><li>1</li></ul><ul style="" class="pre-numbering"><li>1</li></ul>

  该SharedPreferences数据能被其他应用程序读,但不能写。

<code class="hljs mathematica has-numbering"><span class="hljs-keyword">Context</span>.MODE_WORLD_WRITEABLE</code><ul style="" class="pre-numbering"><li>1</li></ul><ul style="" class="pre-numbering"><li>1</li></ul>

  该SharedPreferences数据能被其他应用程序读和写。

<code class="hljs mathematica has-numbering"><span class="hljs-keyword">Context</span>.MODE_MULTI_PROCESS</code><ul style="" class="pre-numbering"><li>1</li></ul><ul style="" class="pre-numbering"><li>1</li></ul>

  sdk2.3后添加的选项,当多个进程同时读写同一个SharedPreferences时它会检查文件是否修改。

2.2  向Shared Preferences中写入值
 
首先要通过 SharedPreferences.Editor获取到Editor对象;

然后通过Editor的putBoolean() 或 putString()等方法存入值;

最后调用Editor的commit()方法提交;

<code class="hljs avrasm has-numbering">//Use <span class="hljs-number">0</span> <span class="hljs-keyword">or</span> MODE_PRIVATE for the default operation 
SharedPreferences settings = getSharedPreferences(<span class="hljs-string">"fanrunqi"</span>, <span class="hljs-number">0</span>)<span class="hljs-comment">;</span>
SharedPreferences<span class="hljs-preprocessor">.Editor</span> editor = settings<span class="hljs-preprocessor">.edit</span>()<span class="hljs-comment">;</span>
editor<span class="hljs-preprocessor">.putBoolean</span>(<span class="hljs-string">"isAmazing"</span>, true)<span class="hljs-comment">; </span>

// 提交本次编辑
editor<span class="hljs-preprocessor">.commit</span>()<span class="hljs-comment">;</span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li></ul>

同时Edit还有两个常用的方法:

editor.remove(String key) :下一次commit的时候会移除key对应的键值对

editor.clear():移除所有键值对

2.3  从Shared Preferences中读取值

  读取值使用 SharedPreference对象的getBoolean()或getString()等方法就行了(没Editor 啥子事)。

<code class="hljs java has-numbering">SharedPreferences settings = getSharedPreferences(<span class="hljs-string">"fanrunqi"</span>, <span class="hljs-number">0</span>);
<span class="hljs-keyword">boolean</span> isAmazing= settings.getBoolean(<span class="hljs-string">"isAmazing"</span>,<span class="hljs-keyword">true</span>);</code><ul style="" class="pre-numbering"><li>1</li><li>2</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li></ul>

2.4  Shared Preferences的优缺点

  可以看出来Preferences是很轻量级的应用,使用起来也很方便,简洁。但存储数据类型比较单一(只有基本数据类型),无法进行条件查询,只能在不复杂的存储需求下使用,比如保存配置信息等。

3、文件数据存储

3.1 使用内部存储

  当文件被保存在内部存储中时,默认情况下,文件是应用程序私有的,其他应用不能访问。当用户卸载应用程序时这些文件也跟着被删除。

  文件默认存储位置:/data/data/包名/files/文件名。

3.1.1 创建和写入一个内部存储的私有文件:

① 调用Context的openFileOutput()函数,填入文件名和操作模式,它会返回一个FileOutputStream对象。

② 通过FileOutputStream对象的write()函数写入数据。

③  FileOutputStream对象的close ()函数关闭流。

例如:

<code class="hljs avrasm has-numbering">        String FILENAME = <span class="hljs-string">"a.txt"</span><span class="hljs-comment">;</span>
        String string = <span class="hljs-string">"fanrunqi"</span><span class="hljs-comment">;</span>

        try {
            FileOutputStream fos = openFileOutput(FILENAME, Context<span class="hljs-preprocessor">.MODE</span>_PRIVATE)<span class="hljs-comment">;</span>
            fos<span class="hljs-preprocessor">.write</span>(string<span class="hljs-preprocessor">.getBytes</span>())<span class="hljs-comment">;</span>
            fos<span class="hljs-preprocessor">.close</span>()<span class="hljs-comment">;</span>
        } catch (Exception e) {
            e<span class="hljs-preprocessor">.printStackTrace</span>()<span class="hljs-comment">;</span>
        }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul>

在 openFileOutput(String name, int mode)方法中

  • name参数: 用于指定文件名称,不能包含路径分隔符“/” ,如果文件不存在,Android 会自动创建它。

  • mode参数:用于指定操作模式,分为四种:

Context.MODE_PRIVATE = 0

  为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容。

Context.MODE_APPEND = 32768

  该模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。 

Context.MODE_WORLD_READABLE = 1

  表示当前文件可以被其他应用读取。

MODE_WORLD_WRITEABLE

  表示当前文件可以被其他应用写入。

3.1.2 读取一个内部存储的私有文件:

① 调用openFileInput( ),参数中填入文件名,会返回一个FileInputStream对象。

② 使用流对象的 read()方法读取字节

③ 调用流的close()方法关闭流

例如:

<code class="hljs go has-numbering">    String FILENAME = <span class="hljs-string">"a.txt"</span>;
        try {
            FileInputStream inStream = openFileInput(FILENAME);
            <span class="hljs-typename">int</span> <span class="hljs-built_in">len</span> =<span class="hljs-number"> 0</span>;
            <span class="hljs-typename">byte</span>[] buf = <span class="hljs-built_in">new</span> <span class="hljs-typename">byte</span><span class="hljs-number">[1024</span>];
            StringBuilder sb = <span class="hljs-built_in">new</span> StringBuilder();
            while ((<span class="hljs-built_in">len</span> = inStream.read(buf)) !=<span class="hljs-number"> -1</span>) {
                sb.<span class="hljs-built_in">append</span>(<span class="hljs-built_in">new</span> String(buf,<span class="hljs-number"> 0</span>, <span class="hljs-built_in">len</span>));
            }
            inStream.<span class="hljs-built_in">close</span>();
        } catch (Exception e) {
            e.printStackTrace();
        } </code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li></ul>

其他一些经常用到的方法:

  • getFilesDir(): 得到内存储文件的绝对路径

  • getDir(): 在内存储空间中创建打开一个已经存在的目录

  • deleteFile(): 删除保存在内部存储的文件。  

  • fileList(): 返回当前由应用程序保存的文件的数组(内存储目录下的全部文件)。 

3.1.3 保存编译时的静态文件

  如果你想在应用编译时保存静态文件,应该把文件保存在项目的 res/raw/ 目录下,你可以通过 openRawResource()方法去打开它(传入参数R.raw.filename),这个方法返回一个 InputStream流对象你可以读取文件但是不能修改原始文件。

<code class="hljs avrasm has-numbering">InputStream is = this<span class="hljs-preprocessor">.getResources</span>()<span class="hljs-preprocessor">.openRawResource</span>(R<span class="hljs-preprocessor">.raw</span><span class="hljs-preprocessor">.filename</span>)<span class="hljs-comment">;</span></code><ul style="" class="pre-numbering"><li>1</li></ul><ul style="" class="pre-numbering"><li>1</li></ul>

3.1.4 保存内存缓存文件

  有时候我们只想缓存一些数据而不是持久化保存,可以使用getCacheDir()去打开一个文件,文件的存储目录( /data/data/包名/cache )是一个应用专门来保存临时缓存文件的内存目录。

  当设备的内部存储空间比较低的时候,Android可能会删除这些缓存文件来恢复空间,但是你不应该依赖系统来回收,要自己维护这些缓存文件把它们的大小限制在一个合理的范围内,比如1MB.当你卸载应用的时候这些缓存文件也会被移除。

3.2 使用外部存储(sdcard)

  因为内部存储容量限制,有时候需要存储数据比较大的时候需要用到外部存储,使用外部存储分为以下几个步骤:

3.2.1 添加外部存储访问限权

 
  首先,要在AndroidManifest.xml中加入访问SDCard的权限,如下:

<code class="hljs xml has-numbering"> <span class="hljs-comment"><!-- 在SDCard中创建与删除文件权限 --></span> 
    <span class="hljs-tag"><<span class="hljs-title">uses-permission</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"android.permission.MOUNT_UNMOUNT_FILESYSTEMS"</span>/></span> 

   <span class="hljs-comment"><!-- 往SDCard写入数据权限 --></span> 
    <span class="hljs-tag"><<span class="hljs-title">uses-permission</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"android.permission.WRITE_EXTERNAL_STORAGE"</span>/></span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>

3.2.2 检测外部存储的可用性

  在使用外部存储时我们需要检测其状态,它可能被连接到计算机、丢失或者只读等。下面代码将说明如何检查状态:

<code class="hljs lasso has-numbering"><span class="hljs-comment">//获取外存储的状态</span>
<span class="hljs-built_in">String</span> state <span class="hljs-subst">=</span> Environment<span class="hljs-built_in">.</span>getExternalStorageState();
<span class="hljs-keyword">if</span> (Environment<span class="hljs-built_in">.</span>MEDIA_MOUNTED<span class="hljs-built_in">.</span><span class="hljs-keyword">equals</span>(state)) {
    <span class="hljs-comment">// 可读可写</span>
    mExternalStorageAvailable <span class="hljs-subst">=</span> mExternalStorageWriteable <span class="hljs-subst">=</span> <span class="hljs-literal">true</span>;
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (Environment<span class="hljs-built_in">.</span>MEDIA_MOUNTED_READ_ONLY<span class="hljs-built_in">.</span><span class="hljs-keyword">equals</span>(state)) {
    <span class="hljs-comment">// 可读</span>
} <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// 可能有很多其他的状态,但是我们只需要知道,不能读也不能写  </span>
}</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul>

3.2.3 访问外部存储器中的文件

1、如果 API 版本大于或等于8,使用

getExternalFilesDir (String type)

  该方法打开一个外存储目录,此方法需要一个类型,指定你想要的子目录,如类型参数DIRECTORY_MUSIC和 DIRECTORY_RINGTONES(传null就是你应用程序的文件目录的根目录)。通过指定目录的类型,确保Android的媒体扫描仪将扫描分类系统中的文件(例如,铃声被确定为铃声)。如果用户卸载应用程序,这个目录及其所有内容将被删除。

例如:

<code class="hljs vhdl has-numbering"><span class="hljs-keyword">File</span> <span class="hljs-keyword">file</span> = <span class="hljs-keyword">new</span> <span class="hljs-keyword">File</span>(getExternalFilesDir(<span class="hljs-keyword">null</span>), <span class="hljs-string">"fanrunqi.jpg"</span>);</code><ul style="" class="pre-numbering"><li>1</li></ul><ul style="" class="pre-numbering"><li>1</li></ul>

2、如果API 版本小于 8 (7或者更低)

getExternalStorageDirectory ()

通过该方法打开外存储的根目录,你应该在以下目录下写入你的应用数据,这样当卸载应用程序时该目录及其所有内容也将被删除。

<code class="hljs haskell has-numbering">/<span class="hljs-type">Android</span>/<span class="hljs-typedef"><span class="hljs-keyword">data</span>/<package_name>/files/</span></code><ul style="" class="pre-numbering"><li>1</li></ul><ul style="" class="pre-numbering"><li>1</li></ul>

读写数据:

<code class="hljs go has-numbering"><span class="hljs-keyword">if</span>(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){  
            File sdCardDir = Environment.getExternalStorageDirectory();<span class="hljs-comment">//获取SDCard目录  "/sdcard"        </span>

               File saveFile = <span class="hljs-built_in">new</span> File(sdCardDir,<span class="hljs-string">"a.txt"</span>); 

               <span class="hljs-comment">//写数据</span>
                try {
                    FileOutputStream fos= <span class="hljs-built_in">new</span> FileOutputStream(saveFile); 
                    fos.write(<span class="hljs-string">"fanrunqi"</span>.getBytes()); 
                    fos.<span class="hljs-built_in">close</span>();
                } catch (Exception e) {
                    e.printStackTrace();
                } 

                <span class="hljs-comment">//读数据</span>
                 try {
                    FileInputStream fis= <span class="hljs-built_in">new</span> FileInputStream(saveFile); 
                    <span class="hljs-typename">int</span> <span class="hljs-built_in">len</span> <span class="hljs-number">=0</span>;
                    <span class="hljs-typename">byte</span>[] buf = <span class="hljs-built_in">new</span> <span class="hljs-typename">byte</span><span class="hljs-number">[1024</span>];
                    StringBuffer sb = <span class="hljs-built_in">new</span> StringBuffer();
                    while((<span class="hljs-built_in">len</span>=fis.read(buf))!<span class="hljs-number">=-1</span>){
                        sb.<span class="hljs-built_in">append</span>(<span class="hljs-built_in">new</span> String(buf,<span class="hljs-number"> 0</span>, <span class="hljs-built_in">len</span>));
                    }
                    fis.<span class="hljs-built_in">close</span>();
                } catch (Exception e) {
                    e.printStackTrace();
                }  
        }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li></ul>

  我们也可以在 /Android/data/package_name/cache/目录下做外部缓存。

部分翻译于:android-data-storage

4、 网络存储数据

HttpUrlConnection

  HttpUrlConnection是Java.net包中提供的API,我们知道Android SDK是基于Java的,所以当然优先考虑HttpUrlConnection这种最原始最基本的API,其实大多数开源的联网框架基本上也是基于JDK的HttpUrlConnection进行的封装罢了,掌握HttpUrlConnection需要以下几个步骤:
  
1、将访问的路径转换成URL。

URL url = new URL(path);

2、通过URL获取连接。

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

3、设置请求方式。

conn.setRequestMethod(GET);

4、设置连接超时时间。

conn.setConnectTimeout(5000);

5、设置请求头的信息。

conn.setRequestProperty(User-Agent, Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0));

7、针对不同的响应码,做不同的操作(请求码200,表明请求成功,获取返回内容的输入流)

工具类:

<code class="hljs java has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StreamTools</span> {</span>
    <span class="hljs-javadoc">/**
     * 将输入流转换成字符串
     * 
     *<span class="hljs-javadoctag"> @param</span> is
     *            从网络获取的输入流
     *<span class="hljs-javadoctag"> @return</span>
     */</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">streamToString</span>(InputStream is) {
        <span class="hljs-keyword">try</span> {
            ByteArrayOutputStream baos = <span class="hljs-keyword">new</span> ByteArrayOutputStream();
            <span class="hljs-keyword">byte</span>[] buffer = <span class="hljs-keyword">new</span> <span class="hljs-keyword">byte</span>[<span class="hljs-number">1024</span>];
            <span class="hljs-keyword">int</span> len = <span class="hljs-number">0</span>;
            <span class="hljs-keyword">while</span> ((len = is.read(buffer)) != -<span class="hljs-number">1</span>) {
                baos.write(buffer, <span class="hljs-number">0</span>, len);
            }
            baos.close();
            is.close();
            <span class="hljs-keyword">byte</span>[] byteArray = baos.toByteArray();
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> String(byteArray);
        } <span class="hljs-keyword">catch</span> (Exception e) {
            Log.e(tag, e.toString());
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
        }
    }
}</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li></ul>

HttpUrlConnection发送GET请求

<code class="hljs cs has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">loginByGet</span>(String username, String password) {
        String path = http:<span class="hljs-comment">//192.168.0.107:8080/WebTest/LoginServerlet?username= + username + &password= + password;</span>
        <span class="hljs-keyword">try</span> {
            URL url = <span class="hljs-keyword">new</span> URL(path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(<span class="hljs-number">5000</span>);
            conn.setRequestMethod(GET);
            <span class="hljs-keyword">int</span> code = conn.getResponseCode();
            <span class="hljs-keyword">if</span> (code == <span class="hljs-number">200</span>) {
                InputStream <span class="hljs-keyword">is</span> = conn.getInputStream(); <span class="hljs-comment">// 字节流转换成字符串</span>
                <span class="hljs-keyword">return</span> StreamTools.streamToString(<span class="hljs-keyword">is</span>);
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-keyword">return</span> 网络访问失败;
            }
        } <span class="hljs-keyword">catch</span> (Exception e) {
            e.printStackTrace();
            <span class="hljs-keyword">return</span> 网络访问失败;
        }
    }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li></ul>

HttpUrlConnection发送POST请求

<code class="hljs lasso has-numbering"><span class="hljs-keyword">public</span> static <span class="hljs-built_in">String</span> loginByPost(<span class="hljs-built_in">String</span> username, <span class="hljs-built_in">String</span> password) {
        <span class="hljs-built_in">String</span> path <span class="hljs-subst">=</span> http:<span class="hljs-comment">//192.168.0.107:8080/WebTest/LoginServerlet;</span>
        try {
            URL url <span class="hljs-subst">=</span> <span class="hljs-literal">new</span> URL(path);
            HttpURLConnection conn <span class="hljs-subst">=</span> (HttpURLConnection) url<span class="hljs-built_in">.</span>openConnection();
            conn<span class="hljs-built_in">.</span>setConnectTimeout(<span class="hljs-number">5000</span>);
            conn<span class="hljs-built_in">.</span>setRequestMethod(POST);
            conn<span class="hljs-built_in">.</span>setRequestProperty(Content<span class="hljs-attribute">-Type</span>, application/x<span class="hljs-attribute">-www</span><span class="hljs-attribute">-form</span><span class="hljs-attribute">-urlencoded</span>);
            <span class="hljs-built_in">String</span> <span class="hljs-built_in">data</span> <span class="hljs-subst">=</span> username<span class="hljs-subst">=</span> <span class="hljs-subst">+</span> username <span class="hljs-subst">+</span> <span class="hljs-subst">&</span>password<span class="hljs-subst">=</span> <span class="hljs-subst">+</span> password;
            conn<span class="hljs-built_in">.</span>setRequestProperty(Content<span class="hljs-attribute">-Length</span>, <span class="hljs-built_in">data</span><span class="hljs-built_in">.</span>length() <span class="hljs-subst">+</span> );
            <span class="hljs-comment">// POST方式,其实就是浏览器把数据写给服务器</span>
            conn<span class="hljs-built_in">.</span>setDoOutput(<span class="hljs-literal">true</span>); <span class="hljs-comment">// 设置可输出流</span>
            OutputStream os <span class="hljs-subst">=</span> conn<span class="hljs-built_in">.</span>getOutputStream(); <span class="hljs-comment">// 获取输出流</span>
            os<span class="hljs-built_in">.</span>write(<span class="hljs-built_in">data</span><span class="hljs-built_in">.</span>getBytes()); <span class="hljs-comment">// 将数据写给服务器</span>
            int code <span class="hljs-subst">=</span> conn<span class="hljs-built_in">.</span>getResponseCode();
            <span class="hljs-keyword">if</span> (code <span class="hljs-subst">==</span> <span class="hljs-number">200</span>) {
                InputStream is <span class="hljs-subst">=</span> conn<span class="hljs-built_in">.</span>getInputStream();
                <span class="hljs-keyword">return</span> StreamTools<span class="hljs-built_in">.</span>streamToString(is);
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-keyword">return</span> 网络访问失败;
            }
        } catch (Exception e) {
            e<span class="hljs-built_in">.</span>printStackTrace();
            <span class="hljs-keyword">return</span> 网络访问失败;
        }
    }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li></ul>

HttpClient

  HttpClient是开源组织Apache提供的Java请求网络框架,其最早是为了方便Java服务器开发而诞生的,是对JDK中的HttpUrlConnection各API进行了封装和简化,提高了性能并且降低了调用API的繁琐,Android因此也引进了这个联网框架,我们再不需要导入任何jar或者类库就可以直接使用,值得注意的是Android官方已经宣布不建议使用HttpClient了。

HttpClient发送GET请求

1、 创建HttpClient对象

2、创建HttpGet对象,指定请求地址(带参数)

3、使用HttpClient的execute(),方法执行HttpGet请求,得到HttpResponse对象

4、调用HttpResponse的getStatusLine().getStatusCode()方法得到响应码

5、调用的HttpResponse的getEntity().getContent()得到输入流,获取服务端写回的数据

<code class="hljs cs has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">loginByHttpClientGet</span>(String username, String password) {
        String path = http:<span class="hljs-comment">//192.168.0.107:8080/WebTest/LoginServerlet?username=</span>
                + username + &password= + password;
        HttpClient client = <span class="hljs-keyword">new</span> DefaultHttpClient(); <span class="hljs-comment">// 开启网络访问客户端</span>
        HttpGet httpGet = <span class="hljs-keyword">new</span> HttpGet(path); <span class="hljs-comment">// 包装一个GET请求</span>
        <span class="hljs-keyword">try</span> {
            HttpResponse response = client.execute(httpGet); <span class="hljs-comment">// 客户端执行请求</span>
            <span class="hljs-keyword">int</span> code = response.getStatusLine().getStatusCode(); <span class="hljs-comment">// 获取响应码</span>
            <span class="hljs-keyword">if</span> (code == <span class="hljs-number">200</span>) {
                InputStream <span class="hljs-keyword">is</span> = response.getEntity().getContent(); <span class="hljs-comment">// 获取实体内容</span>
                String result = StreamTools.streamToString(<span class="hljs-keyword">is</span>); <span class="hljs-comment">// 字节流转字符串</span>
                <span class="hljs-keyword">return</span> result;
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-keyword">return</span> 网络访问失败;
            }
        } <span class="hljs-keyword">catch</span> (Exception e) {
            e.printStackTrace();
            <span class="hljs-keyword">return</span> 网络访问失败;
        }
    }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li></ul>

HttpClient发送POST请求

1,创建HttpClient对象

2,创建HttpPost对象,指定请求地址

3,创建List,用来装载参数

4,调用HttpPost对象的setEntity()方法,装入一个UrlEncodedFormEntity对象,携带之前封装好的参数

5,使用HttpClient的execute()方法执行HttpPost请求,得到HttpResponse对象

6, 调用HttpResponse的getStatusLine().getStatusCode()方法得到响应码

7, 调用的HttpResponse的getEntity().getContent()得到输入流,获取服务端写回的数据

<code class="hljs cs has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">loginByHttpClientPOST</span>(String username, String password) {
        String path = http:<span class="hljs-comment">//192.168.0.107:8080/WebTest/LoginServerlet;</span>
        <span class="hljs-keyword">try</span> {
            HttpClient client = <span class="hljs-keyword">new</span> DefaultHttpClient(); <span class="hljs-comment">// 建立一个客户端</span>
            HttpPost httpPost = <span class="hljs-keyword">new</span> HttpPost(path); <span class="hljs-comment">// 包装POST请求</span>
            <span class="hljs-comment">// 设置发送的实体参数</span>
            List parameters = <span class="hljs-keyword">new</span> ArrayList();
            parameters.add(<span class="hljs-keyword">new</span> BasicNameValuePair(username, username));
            parameters.add(<span class="hljs-keyword">new</span> BasicNameValuePair(password, password));
            httpPost.setEntity(<span class="hljs-keyword">new</span> UrlEncodedFormEntity(parameters, UTF-<span class="hljs-number">8</span>));
            HttpResponse response = client.execute(httpPost); <span class="hljs-comment">// 执行POST请求</span>
            <span class="hljs-keyword">int</span> code = response.getStatusLine().getStatusCode();
            <span class="hljs-keyword">if</span> (code == <span class="hljs-number">200</span>) {
                InputStream <span class="hljs-keyword">is</span> = response.getEntity().getContent();
                String result = StreamTools.streamToString(<span class="hljs-keyword">is</span>);
                <span class="hljs-keyword">return</span> result;
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-keyword">return</span> 网络访问失败;
            }
        } <span class="hljs-keyword">catch</span> (Exception e) {
            e.printStackTrace();
            <span class="hljs-keyword">return</span> 访问网络失败;
        }
    }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li></ul>

参考:

  Android开发请求网络方式详解

Android提供的其他网络访问框架

  HttpClient和HttpUrlConnection的两种网络访问方式编写网络代码,需要自己考虑很多,获取数据或许可以,但是如果要将手机本地数据上传至网络,根据不同的web端接口,需要组织不同的数据内容上传,给手机端造成了很大的工作量。
  
  目前有几种快捷的网络开发开源框架,给我们提供了非常大的便利。下面是这些项目Github地址,有文档和Api说明。
  
android-async-http 

http-request

okhttp

5、 SQLite数据库存储数据

  
  前面的文章 SQLite的使用入门已经做了详细说明,这里就不在多说了。

6、 使用ContentProvider存储数据 

ContentProvider(内容提供者)是Android的四大组件之一,管理android以结构化方式存放的数据,以相对安全的方式封装数据(表)并且提供简易的处理机制和统一的访问接口供其他程序调用。 
  
  Android的数据存储方式总共有五种,分别是:Shared Preferences、网络存储、文件存储、外储存储、SQLite。但一般这些存储都只是在单独的一个应用程序之中达到一个数据的共享,有时候我们需要操作其他应用程序的一些数据,就会用到ContentProvider。而且Android为常见的一些数据提供了默认的ContentProvider(包括音频、视频、图片和通讯录等)。

  但注意ContentProvider它也只是一个中间人,真正操作的数据源可能是数据库,也可以是文件、xml或网络等其他存储方式。

2.URL

  URL(统一资源标识符)代表要操作的数据,可以用来标识每个ContentProvider,这样你就可以通过指定的URI找到想要的ContentProvider,从中获取或修改数据。
  在Android中URI的格式如下图所示:

这里写图片描述 


  •  
       schema,已经由Android所规定为:content://. 
       
  •    主机名(Authority),是URI的授权部分,是唯一标识符,用来定位ContentProvider。

C部分和D部分:是每个ContentProvider内部的路径部分

  •    指向一个对象集合,一般用表的名字,如果没有指定D部分,则返回全部记录。

  •    指向特定的记录,这里表示操作user表id为7的记录。如果要操作user表中id为7的记录的name字段, D部分变为 /7/name即可。

URI模式匹配通配符

*:匹配的任意长度的任何有效字符的字符串。

#:匹配的任意长度的数字字符的字符串。

如:

content://com.example.app.provider/*
匹配provider的任何内容url

content://com.example.app.provider/table3/#
匹配table3的所有行

2.1MIME

  MIME是指定某个扩展名的文件用一种应用程序来打开,就像你用浏览器查看PDF格式的文件,浏览器会选择合适的应用来打开一样。Android中的工作方式跟HTTP类似,ContentProvider会根据URI来返回MIME类型,ContentProvider会返回一个包含两部分的字符串。MIME类型一般包含两部分,如:

text/html
text/css
text/xml
application/pdf

  分为类型和子类型,Android遵循类似的约定来定义MIME类型,每个内容类型的Android MIME类型有两种形式:多条记录(集合)和单条记录。

  集合记录:

<code class="hljs avrasm has-numbering">vnd<span class="hljs-preprocessor">.android</span><span class="hljs-preprocessor">.cursor</span><span class="hljs-preprocessor">.dir</span>/自定义</code><ul style="" class="pre-numbering"><li>1</li></ul><ul style="" class="pre-numbering"><li>1</li></ul>

  单条记录:

<code class="hljs avrasm has-numbering">vnd<span class="hljs-preprocessor">.android</span><span class="hljs-preprocessor">.cursor</span><span class="hljs-preprocessor">.item</span>/自定义</code><ul style="" class="pre-numbering"><li>1</li></ul><ul style="" class="pre-numbering"><li>1</li></ul>

  vnd表示这些类型和子类型具有非标准的、供应商特定的形式。Android中类型已经固定好了,不能更改,只能区别是集合还是单条具体记录,子类型可以按照格式自己填写。
  在使用Intent时,会用到MIME,根据Mimetype打开符合条件的活动。

  下面分别介绍Android系统提供了两个用于操作Uri的工具类:ContentUris和UriMatcher。

2.2 ContentUris

  ContetnUris包含一个便利的函数withAppendedId()来向URI追加一个id。

<code class="hljs avrasm has-numbering">Uri uri = Uri<span class="hljs-preprocessor">.parse</span>(<span class="hljs-string">"content://cn.scu.myprovider/user"</span>)
Uri resultUri = ContentUris<span class="hljs-preprocessor">.withAppendedId</span>(uri, <span class="hljs-number">7</span>)<span class="hljs-comment">; </span>

//生成后的Uri为:content://cn<span class="hljs-preprocessor">.scu</span><span class="hljs-preprocessor">.myprovider</span>/user/<span class="hljs-number">7</span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul>

  同时提供parseId(uri)方法用于从URL中获取ID:

<code class="hljs cs has-numbering">Uri uri = Uri.parse(<span class="hljs-string">"content://cn.scu.myprovider/user/7"</span>)
<span class="hljs-keyword">long</span> personid = ContentUris.parseId(uri);
<span class="hljs-comment">//获取的结果为:7</span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul>

2.3UriMatcher

  UriMatcher本质上是一个文本过滤器,用在contentProvider中帮助我们过滤,分辨出查询者想要查询哪个数据表。

  举例说明:

  • 第一步,初始化:
<code class="hljs cs has-numbering">UriMatcher matcher = <span class="hljs-keyword">new</span> UriMatcher(UriMatcher.NO_MATCH);
<span class="hljs-comment">//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码</span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li></ul>
  • 第二步,注册需要的Uri:
<code class="hljs avrasm has-numbering">//USER 和 USER_ID是两个int型数据
matcher<span class="hljs-preprocessor">.addURI</span>(<span class="hljs-string">"cn.scu.myprovider"</span>, <span class="hljs-string">"user"</span>, USER)<span class="hljs-comment">;</span>
matcher<span class="hljs-preprocessor">.addURI</span>(<span class="hljs-string">"cn.scu.myprovider"</span>, <span class="hljs-string">"user/#"</span>,USER_ID)<span class="hljs-comment">;</span>
//如果match()方法匹配content://cn<span class="hljs-preprocessor">.scu</span><span class="hljs-preprocessor">.myprovider</span>/user路径,返回匹配码为USER</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul>
  • 第三部,与已经注册的Uri进行匹配:
<code class="hljs java has-numbering"><span class="hljs-comment">/* 
     * 如果操作集合,则必须以vnd.android.cursor.dir开头 
     * 如果操作非集合,则必须以vnd.android.cursor.item开头 
     * */</span>  
    <span class="hljs-annotation">@Override</span>  
    <span class="hljs-keyword">public</span> String <span class="hljs-title">getType</span>(Uri uri) {  
    Uri uri = Uri.parse(<span class="hljs-string">"content://"</span> + <span class="hljs-string">"cn.scu.myprovider"</span> + <span class="hljs-string">"/user"</span>);  
        <span class="hljs-keyword">switch</span>(matcher.match(uri)){  
        <span class="hljs-keyword">case</span> USER:  
            <span class="hljs-keyword">return</span> <span class="hljs-string">"vnd.android.cursor.dir/user"</span>;  
        <span class="hljs-keyword">case</span> USER_ID:  
            <span class="hljs-keyword">return</span> <span class="hljs-string">"vnd.android.cursor.item/user"</span>;  
        }  
    } </code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li></ul>

3.ContentProvider的主要方法

public boolean onCreate()

  ContentProvider创建后 或 打开系统后其它应用第一次访问该ContentProvider时调用。

public Uri insert(Uri uri, ContentValues values)

  外部应用向ContentProvider中添加数据。

public int delete(Uri uri, String selection, String[] selectionArgs)

  外部应用从ContentProvider删除数据。

public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs):

  外部应用更新ContentProvider中的数据。

public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 

  供外部应用从ContentProvider中获取数据。
 

public String getType(Uri uri)

  该方法用于返回当前Url所代表数据的MIME类型。

4.ContentResolver

  ContentResolver通过URI来查询ContentProvider中提供的数据。除了URI以 外,还必须知道需要获取的数据段的名称,以及此数据段的数据类型。如果你需要获取一个特定的记录,你就必须知道当前记录的ID,也就是URI中D部分。

  ContentResolver 类提供了与ContentProvider类相同签名的四个方法:

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)//获取

实例代码:

<code class="hljs actionscript has-numbering">ContentResolver resolver =  getContentResolver();
Uri uri = Uri.parse(<span class="hljs-string">"content://cn.scu.myprovider/user"</span>);

<span class="hljs-comment">//添加一条记录</span>
ContentValues values = <span class="hljs-keyword">new</span> ContentValues();
values.put(<span class="hljs-string">"name"</span>, <span class="hljs-string">"fanrunqi"</span>);
values.put(<span class="hljs-string">"age"</span>, <span class="hljs-number">24</span>);
resolver.insert(uri, values);  

<span class="hljs-comment">//获取user表中所有记录</span>
Cursor cursor = resolver.query(uri, <span class="hljs-literal">null</span>, <span class="hljs-literal">null</span>, <span class="hljs-literal">null</span>, <span class="hljs-string">"userid desc"</span>);
<span class="hljs-keyword">while</span>(cursor.moveToNext()){
   <span class="hljs-comment">//操作</span>
}

<span class="hljs-comment">//把id为1的记录的name字段值更改新为finch</span>
ContentValues updateValues = <span class="hljs-keyword">new</span> ContentValues();
updateValues.put(<span class="hljs-string">"name"</span>, <span class="hljs-string">"finch"</span>);
Uri updateIdUri = ContentUris.withAppendedId(uri, <span class="hljs-number">1</span>);
resolver.update(updateIdUri, updateValues, <span class="hljs-literal">null</span>, <span class="hljs-literal">null</span>);

<span class="hljs-comment">//删除id为2的记录</span>
Uri deleteIdUri = ContentUris.withAppendedId(uri, <span class="hljs-number">2</span>);
resolver.<span class="hljs-keyword">delete</span>(deleteIdUri, <span class="hljs-literal">null</span>, <span class="hljs-literal">null</span>);</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li></ul>

5.ContentObserver

    ContentObserver(内容观察者),目的是观察特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它.

下面是使用内容观察者监听短信的例子:
<code class="hljs java has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Activity</span> {</span>

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span>(Bundle savedInstanceState) {
        <span class="hljs-keyword">super</span>.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

<span class="hljs-comment">//注册观察者Observser    </span>
<span class="hljs-keyword">this</span>.getContentResolver().registerContentObserver(Uri.parse(<span class="hljs-string">"content://sms"</span>),<span class="hljs-keyword">true</span>,<span class="hljs-keyword">new</span> SMSObserver(<span class="hljs-keyword">new</span> Handler()));

    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SMSObserver</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ContentObserver</span> {</span>

        <span class="hljs-keyword">public</span> <span class="hljs-title">SMSObserver</span>(Handler handler) {
            <span class="hljs-keyword">super</span>(handler);

        }


        <span class="hljs-annotation">@Override</span>
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onChange</span>(<span class="hljs-keyword">boolean</span> selfChange) {

 Cursor cursor = MainActivity.<span class="hljs-keyword">this</span>.getContentResolver().query(
Uri.parse(<span class="hljs-string">"content://sms/inbox"</span>), <span class="hljs-keyword">null</span>, <span class="hljs-keyword">null</span>, <span class="hljs-keyword">null</span>, <span class="hljs-keyword">null</span>);

            <span class="hljs-keyword">while</span> (cursor.moveToNext()) {
                StringBuilder sb = <span class="hljs-keyword">new</span> StringBuilder();

                sb.append(<span class="hljs-string">"address="</span>).append(
                        cursor.getString(cursor.getColumnIndex(<span class="hljs-string">"address"</span>)));

                sb.append(<span class="hljs-string">";subject="</span>).append(
                        cursor.getString(cursor.getColumnIndex(<span class="hljs-string">"subject"</span>)));

                sb.append(<span class="hljs-string">";body="</span>).append(
                        cursor.getString(cursor.getColumnIndex(<span class="hljs-string">"body"</span>)));

                sb.append(<span class="hljs-string">";time="</span>).append(
                        cursor.getLong(cursor.getColumnIndex(<span class="hljs-string">"date"</span>)));

                System.out.println(<span class="hljs-string">"--------has Receivered SMS::"</span> + sb.toString());


            }

        }

    }
}</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li></ul>

同时可以在ContentProvider发生数据变化时调用
getContentResolver().notifyChange(uri, null)来通知注册在此URI上的访问者。

<code class="hljs java has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserContentProvider</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ContentProvider</span> {</span>
   <span class="hljs-keyword">public</span> Uri <span class="hljs-title">insert</span>(Uri uri, ContentValues values) {
      db.insert(<span class="hljs-string">"user"</span>, <span class="hljs-string">"userid"</span>, values);
      getContext().getContentResolver().notifyChange(uri, <span class="hljs-keyword">null</span>);
   }
}</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li></ul>

6.实例说明

  数据源是SQLite, 用ContentResolver操作ContentProvider。

这里写图片描述

Constant.Java(储存一些常量)

<code class="hljs java has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Constant</span> {</span>  

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String TABLE_NAME = <span class="hljs-string">"user"</span>;  

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String COLUMN_ID = <span class="hljs-string">"_id"</span>;  
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String COLUMN_NAME = <span class="hljs-string">"name"</span>;  


    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String AUTOHORITY = <span class="hljs-string">"cn.scu.myprovider"</span>;  
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> ITEM = <span class="hljs-number">1</span>;  
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> ITEM_ID = <span class="hljs-number">2</span>;  

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String CONTENT_TYPE = <span class="hljs-string">"vnd.android.cursor.dir/user"</span>;  
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String CONTENT_ITEM_TYPE = <span class="hljs-string">"vnd.android.cursor.item/user"</span>;  

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Uri CONTENT_URI = Uri.parse(<span class="hljs-string">"content://"</span> + AUTOHORITY + <span class="hljs-string">"/user"</span>);  
}  </code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li></ul>

DBHelper.java(操作数据库)

<code class="hljs java has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DBHelper</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">SQLiteOpenHelper</span> {</span>  

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String DATABASE_NAME = <span class="hljs-string">"finch.db"</span>;    
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> DATABASE_VERSION = <span class="hljs-number">1</span>;    

    <span class="hljs-keyword">public</span> <span class="hljs-title">DBHelper</span>(Context context) {  
        <span class="hljs-keyword">super</span>(context, DATABASE_NAME, <span class="hljs-keyword">null</span>, DATABASE_VERSION);  
    }  

    <span class="hljs-annotation">@Override</span>  
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span>(SQLiteDatabase db)  <span class="hljs-keyword">throws</span> SQLException {  
        <span class="hljs-comment">//创建表格  </span>
        db.execSQL(<span class="hljs-string">"CREATE TABLE IF NOT EXISTS "</span>+ Constant.TABLE_NAME + <span class="hljs-string">"("</span>+ Constant.COLUMN_ID +<span class="hljs-string">" INTEGER PRIMARY KEY AUTOINCREMENT,"</span> + Constant.COLUMN_NAME +<span class="hljs-string">" VARCHAR NOT NULL);"</span>);  
    }  

    <span class="hljs-annotation">@Override</span>  
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onUpgrade</span>(SQLiteDatabase db, <span class="hljs-keyword">int</span> oldVersion, <span class="hljs-keyword">int</span> newVersion)  <span class="hljs-keyword">throws</span> SQLException {  
        <span class="hljs-comment">//删除并创建表格  </span>
        db.execSQL(<span class="hljs-string">"DROP TABLE IF EXISTS "</span>+ Constant.TABLE_NAME+<span class="hljs-string">";"</span>);  
        onCreate(db);  
    }  
}  
</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li></ul>

 MyProvider.java(自定义的ContentProvider) 

<code class="hljs java has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyProvider</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ContentProvider</span> {</span>    

    DBHelper mDbHelper = <span class="hljs-keyword">null</span>;    
    SQLiteDatabase db = <span class="hljs-keyword">null</span>;    

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> UriMatcher mMatcher;    
    <span class="hljs-keyword">static</span>{    
        mMatcher = <span class="hljs-keyword">new</span> UriMatcher(UriMatcher.NO_MATCH);    
        mMatcher.addURI(Constant.AUTOHORITY,Constant.TABLE_NAME, Constant.ITEM);    
        mMatcher.addURI(Constant.AUTOHORITY, Constant.TABLE_NAME+<span class="hljs-string">"/#"</span>, Constant.ITEM_ID);    
    }    


    <span class="hljs-annotation">@Override</span>    
    <span class="hljs-keyword">public</span> String <span class="hljs-title">getType</span>(Uri uri) {    
        <span class="hljs-keyword">switch</span> (mMatcher.match(uri)) {    
        <span class="hljs-keyword">case</span> Constant.ITEM:    
            <span class="hljs-keyword">return</span> Constant.CONTENT_TYPE;    
        <span class="hljs-keyword">case</span> Constant.ITEM_ID:    
            <span class="hljs-keyword">return</span> Constant.CONTENT_ITEM_TYPE;    
        <span class="hljs-keyword">default</span>:    
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalArgumentException(<span class="hljs-string">"Unknown URI"</span>+uri);    
        }    
    }    

    <span class="hljs-annotation">@Override</span>    
    <span class="hljs-keyword">public</span> Uri <span class="hljs-title">insert</span>(Uri uri, ContentValues values) {    
        <span class="hljs-comment">// TODO Auto-generated method stub    </span>
        <span class="hljs-keyword">long</span> rowId;    
        <span class="hljs-keyword">if</span>(mMatcher.match(uri)!=Constant.ITEM){    
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalArgumentException(<span class="hljs-string">"Unknown URI"</span>+uri);    
        }    
        rowId = db.insert(Constant.TABLE_NAME,<span class="hljs-keyword">null</span>,values);    
        <span class="hljs-keyword">if</span>(rowId><span class="hljs-number">0</span>){    
            Uri noteUri=ContentUris.withAppendedId(Constant.CONTENT_URI, rowId);    
            getContext().getContentResolver().notifyChange(noteUri, <span class="hljs-keyword">null</span>);    
            <span class="hljs-keyword">return</span> noteUri;    
        }    

        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> SQLException(<span class="hljs-string">"Failed to insert row into "</span> + uri);    
    }    

    <span class="hljs-annotation">@Override</span>    
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">onCreate</span>() {    
        <span class="hljs-comment">// TODO Auto-generated method stub    </span>
        mDbHelper = <span class="hljs-keyword">new</span> DBHelper(getContext());    

        db = mDbHelper.getReadableDatabase();    

        <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;    
    }    

    <span class="hljs-annotation">@Override</span>    
    <span class="hljs-keyword">public</span> Cursor <span class="hljs-title">query</span>(Uri uri, String[] projection, String selection,    
            String[] selectionArgs, String sortOrder) {    
        <span class="hljs-comment">// TODO Auto-generated method stub    </span>
        Cursor c = <span class="hljs-keyword">null</span>;    
        <span class="hljs-keyword">switch</span> (mMatcher.match(uri)) {    
        <span class="hljs-keyword">case</span> Constant.ITEM:    
            c =  db.query(Constant.TABLE_NAME, projection, selection, selectionArgs, <span class="hljs-keyword">null</span>, <span class="hljs-keyword">null</span>, sortOrder);    
            <span class="hljs-keyword">break</span>;    
        <span class="hljs-keyword">case</span> Constant.ITEM_ID:    
            c = db.query(Constant.TABLE_NAME, projection,Constant.COLUMN_ID + <span class="hljs-string">"="</span>+uri.getLastPathSegment(), selectionArgs, <span class="hljs-keyword">null</span>, <span class="hljs-keyword">null</span>, sortOrder);    
            <span class="hljs-keyword">break</span>;    
        <span class="hljs-keyword">default</span>:    
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalArgumentException(<span class="hljs-string">"Unknown URI"</span>+uri);    
        }    

        c.setNotificationUri(getContext().getContentResolver(), uri);    
        <span class="hljs-keyword">return</span> c;    
    }    

    <span class="hljs-annotation">@Override</span>    
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">update</span>(Uri uri, ContentValues values, String selection,    
            String[] selectionArgs) {    
        <span class="hljs-comment">// TODO Auto-generated method stub    </span>
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;    
    }

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">delete</span>(Uri uri, String selection, String[] selectionArgs) {
        <span class="hljs-comment">// TODO Auto-generated method stub</span>
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
    }    

}    </code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li><li>54</li><li>55</li><li>56</li><li>57</li><li>58</li><li>59</li><li>60</li><li>61</li><li>62</li><li>63</li><li>64</li><li>65</li><li>66</li><li>67</li><li>68</li><li>69</li><li>70</li><li>71</li><li>72</li><li>73</li><li>74</li><li>75</li><li>76</li><li>77</li><li>78</li><li>79</li><li>80</li><li>81</li><li>82</li><li>83</li><li>84</li><li>85</li><li>86</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li><li>54</li><li>55</li><li>56</li><li>57</li><li>58</li><li>59</li><li>60</li><li>61</li><li>62</li><li>63</li><li>64</li><li>65</li><li>66</li><li>67</li><li>68</li><li>69</li><li>70</li><li>71</li><li>72</li><li>73</li><li>74</li><li>75</li><li>76</li><li>77</li><li>78</li><li>79</li><li>80</li><li>81</li><li>82</li><li>83</li><li>84</li><li>85</li><li>86</li></ul>

MainActivity.java(ContentResolver操作)

<code class="hljs java has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Activity</span> {</span>
    <span class="hljs-keyword">private</span> ContentResolver mContentResolver = <span class="hljs-keyword">null</span>; 
    <span class="hljs-keyword">private</span> Cursor cursor = <span class="hljs-keyword">null</span>;  
         <span class="hljs-annotation">@Override</span>
        <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span>(Bundle savedInstanceState) {
            <span class="hljs-comment">// TODO Auto-generated method stub</span>
            <span class="hljs-keyword">super</span>.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

               TextView tv = (TextView) findViewById(R.id.tv);

                mContentResolver = getContentResolver();  
                tv.setText(<span class="hljs-string">"添加初始数据 "</span>);
                <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < <span class="hljs-number">10</span>; i++) {  
                    ContentValues values = <span class="hljs-keyword">new</span> ContentValues();  
                    values.put(Constant.COLUMN_NAME, <span class="hljs-string">"fanrunqi"</span>+i);  
                    mContentResolver.insert(Constant.CONTENT_URI, values);  
                } 

                tv.setText(<span class="hljs-string">"查询数据 "</span>);
                cursor = mContentResolver.query(Constant.CONTENT_URI, <span class="hljs-keyword">new</span> String[]{Constant.COLUMN_ID,Constant.COLUMN_NAME}, <span class="hljs-keyword">null</span>, <span class="hljs-keyword">null</span>, <span class="hljs-keyword">null</span>);  
                <span class="hljs-keyword">if</span> (cursor.moveToFirst()) {
                    String s = cursor.getString(cursor.getColumnIndex(Constant.COLUMN_NAME));
                    tv.setText(<span class="hljs-string">"第一个数据: "</span>+s);
                }
        }

}  
</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li></ul>

最后在manifest申明

<code class="hljs xml has-numbering"><span class="hljs-tag"><<span class="hljs-title">provider</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"MyProvider"</span> <span class="hljs-attribute">android:authorities</span>=<span class="hljs-value">"cn.scu.myprovider"</span> /></span></code>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值