我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android系统的五种数据存储形式实例(二)

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android系统的五种数据存储形式实例(二)

之前介绍了Android系统下三种数据存储形式,//www.jb51.net/article/99468.htm。今天补充介绍另外两种,分别是内容提供者和网络存储。有些人可能认为内存提供者和网络存储更偏向于对数据的操作而不是数据的存储,但这两种方式确实与数据有关,所以这里还是将这两种形式简要的说明一下。

 Content Provider:

Content Provider,中文名是内存提供者,Android四大组件之一,内容提供者是应用程序之间共享数据的接口,以数据库形式存入手机内存,可以共享自己的数据给其他应用使用。之所以需要设计一个单独的控件来操作数据,是为了实现应用程序之间的数据传递。通过查看DDMS中的目录结构可以看出,数据库文件对于其他应用来说是不可读、不可写,而日常生活中又需要获取其他应用的数据,尤其是系统自带软件的数据。比如打开QQ或者微信时会提示是否同步联系人,又比如备份短信的时候,这些都需要访问和操作其他应用的数据库。因此谷歌工程师在底层软件中集成了大量的方法利用内存提供者的原理,类似于在数据库中提供一个对外访问的路径,供其他应用访问。

为了更好的理解内存提供者的工作原理,可以自定义一个内容提示者来帮助理解。首先写一个类继承ContentProvider,实现该类中的方法,包括一些增删改查和数据初始化的方法,可以在方法中实现对数据库的增删改查操作。数据库本来是不对外开放的,所以为保护数据,类中的方法原始返回数据均是空类型。为保证数据的安全性,可以创建一个UriMatcher对象,利用addURIf方法添加Uri的路径规则,在每一次进行数据操作时先判断传入的路径是否符合命名规则。使用内存提供者需要在配置文件中添加provider标签,指定主机名。只有当访问者与内容提供者的主机名一致时,才可以建立数据连接。在另一个应用中实现对内存提供者的访问。具体操作是:创建内容提供者解析器,定义要访问的Uri的路径。Uri路径有着固定的格式:”content://主机名/匹配字符”。 利用内容提供者解析器进行增删改查,和要操作的数据库之间建立联系。以上内容通常用来理解内容提供者的工作原理,实际工作中很少用到自定义的内容提示者。实际中用的比较多的是用内容提供者操作系统联系人、系统短信等系统应用的数据库。

内容提供者操作系统应用时相对简单,需要用到的大部分程序已经在底层实现,要做的是调用各种方法和相关的参数。需要关注的参数有Uri路径、数据库的表单结构。可以通过查看底层的代码获取相应的参数。其中有些常用的参数可以记下来,方便调用。比如获取全部短信的Uri路径是: content://sms。与联系人有关的数据库表单有三个raw_contacts、data、mimetypes。操作raw_contacts 表的Uri是: content://com.android.contacts/raw_contacts,操作data 表的Uri是:content://com.android.contacts/data。本文以短信的备份、还原来演示利用内容提供者访问短信数据库。

 先看一下短信和手机联系人有关的数据库所在的路径。短信在Android 模拟器下存放在的路径是:/data/data/com.android.providers.telephony/databases/目录,联系人在Android 模拟器下存放在的路径是:/data/data/com.android.providers.contacts/databases/目录。对于短信数据库我们关心的表数据有:address、type、body、date,分别表示发送者号码、短信类型(收还是发)、短信内容、日期。对于联系人数据库的三张表一定要按照一定的顺序依次查找才能得到相关的数据,在这不做解释。尽管开发的时候不需要了解短信和手机联系人的数据库路径,但是要明白短信和手机联系人的数据是存在数据库中的,同时数据库对外是不开放的。

与短信有关的数据库的目录结构:

本文给出的案例是短信的备份和还原,从而实现对系统应用数据库的操作。首先利用内容提供者查询到短信数据库里的详细参数,将该数据以Xml文件的形式存入到指定的文件夹。利用xml解析得到数据,将获取的数据存在一个工具类中,这样就能用ListView将数据显示在界面上。具体实现如下。


package com.example.contentprovider; 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;
import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.util.Xml;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

 public class MainActivity extends Activity {
  private static final String TAG = "MainActivity";
  private ListView lv;
  private List<Person> mlist;
  private Myadpter adapter;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    lv = (ListView) findViewById(R.id.lv);
    datafresh();
  }
  //数据刷新,一般用到ListView时最好记得刷新数据否则不显示
  public void datafresh(){
    mlist = getList();
    if(adapter == null){
      adapter = new Myadpter();
    }else {
      adapter.notifyDataSetChanged();
    }
  }
  //用ListView显示短信内容
  public class Myadpter extends BaseAdapter{
    public int getCount() {
      // TODO Auto-generated method stub
      return mlist.size();
    }
    public Object getItem(int position) {
      // TODO Auto-generated method stub
      return null;
    }
    public long getItemId(int position) {
      // TODO Auto-generated method stub
      return 0;
    }
    public View getView(int position, View convertView, ViewGroup parent) {
      TextView tv = new TextView(MainActivity.this);
      tv.setText(mlist.get(position).toString());
      return tv;
    }
  }
  //短信备份 
  public void bankup(View view){
    ContentResolver resolver = getContentResolver();
    Uri uri = Uri.parse("content://sms");
    Cursor cursor = resolver.query(uri, new String[]{"address","body","type","date"}, null, null, null);
    while(cursor.moveToNext()){
      String address = cursor.getString(0);
      String body = cursor.getString(1);
      String type = cursor.getString(2);
      String date = cursor.getString(3);
      //序列化,把短信以Xml文件的形式存储
      XmlSerializer serializer = Xml.newSerializer();
      File file = new File(getFilesDir(),"info.xml");
      try {
        FileOutputStream fos = new FileOutputStream(file);
        serializer.setOutput(fos, "utf-8");
        serializer.startDocument("utf-8", true);
        serializer.startTag(null, "person");
        serializer.startTag(null, "address");
        serializer.text(address);
        serializer.endTag(null, "address");
        serializer.startTag(null, "body");
        serializer.text(body);
        serializer.endTag(null, "body");
        serializer.startTag(null, "type");
        serializer.text(type);
        serializer.endTag(null, "type");
        serializer.startTag(null, "date");
        serializer.text(date);
        serializer.endTag(null, "date");
        serializer.endTag(null, "person");
        serializer.endDocument();
        fos.close();
//       Toast.makeText(this, "数据保存成功", 0).show();
      } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
  }
  public void restore(View view){
    datafresh();
    lv.setAdapter(adapter);
  }
  //利用Xml解析得到短信内容
  private List<Person> getList() {
    ContentResolver resolver = getContentResolver();
    List<Person> list = new ArrayList();//创建一个Person类存储标签内容
    Person p = new Person();
    File file = new File(getFilesDir(),"info.xml");
    XmlPullParser pullParser = Xml.newPullParser();
    try {
      FileInputStream fis = new FileInputStream(file);
      pullParser.setInput(fis, "utf-8");
      int mtype = pullParser.getEventType();
      while(mtype != XmlPullParser.END_DOCUMENT){
        String name = pullParser.getName();
        switch (mtype){
        case XmlPullParser.START_TAG:
          if("address".equals(name)){
            String address = pullParser.nextText();
            p.setAddress(address);
          }else if("body".equals(name)){
            String body = pullParser.nextText();
            p.setBody(body);
          }else if("type".equals(name)){
            String type = pullParser.nextText();
            p.setType(type);
          }else if("date".equals(name)){
            String date = pullParser.nextText();
            p.setDate(date);
          }
          break;
        case XmlPullParser.END_TAG:
          if("person".equals(name)){
            list.add(p);
          }
          break;
        }
        mtype = pullParser.next();
      }
      Log.i(TAG, list.toString());
      return list;
    } catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      return null;
    }
  }
} 

效果演示,我的虚拟机中只存了一条短信:

网络存储:

网络存储是最容易理解的一种存储方式了。其实说简单点就是文件的上传和下载。经常听到的云备份就是这种形式。优势也很明显,即把数据存储到服务器,不存储在本地,使用的时候直接从网络获取,避免了手机端信息丢失以及其他的安全隐患。因此,对于这种形式就不作多的解释,直接给出一个文件的上传和下载的实例来演示网络存储。

代码实现:


package com.example.upload;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import org.apache.http.Header;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.RequestParams;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.text.TextUtils;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends Activity {
  protected static final int SUCCESS = 1;
  protected static final int ERORR = 2;
  private EditText et_path;
  private ImageView iv;
  //访问网络操作耗时,需要在子线程中加一个代理
  private Handler handler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
      switch (msg.what) {
      case SUCCESS:
        Bitmap bm = (Bitmap) msg.obj;
        iv.setImageBitmap(bm);
        break;
      case ERORR:
        Toast.makeText(MainActivity.this, "图片获取失败", 0).show();
        break;
      }
      super.handleMessage(msg);
    }};
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    et_path = (EditText) findViewById(R.id.et_path);
    iv = (ImageView) findViewById(R.id.iv);
  }
  //上传程序
  public void upload(View view){
//    String path = et_path.getText().toString().trim();
//    这里为方便把路径写死,这种方式不太正规,一般可以读et_path来访问
    String path = "/mnt/sdcard/info.txt";
    if(TextUtils.isEmpty(path)){
      Toast.makeText(this, "路径不能为空", 0).show();
      return;
    }
    File file = new File(path);
    AsyncHttpClient client = new AsyncHttpClient();
    RequestParams param = new RequestParams();
    try {
      param.put("file", file);
    } catch (FileNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    client.post("http://192.168.1.114:8080/",param, new AsyncHttpResponseHandler() {
      @Override
      public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
        // TODO Auto-generated method stub
        Toast.makeText(MainActivity.this, "提交成功", 0).show();
      }
      @Override
      public void onFailure(int statusCode, Header[] headers,
          byte[] responseBody, Throwable error) {
        // TODO Auto-generated method stub
        Toast.makeText(MainActivity.this, "提交失败", 0).show();
      }
    });
  }
  //下载程序  
  public void download(View view){
    new Thread(){
      public void run() {
        try {
          //这里为方便把路径写死,可以读et_path来访问,两者结果一样
          URL url = new URL("http://192.168.1.114:8080/demo1.png");
          HttpURLConnection conn = (HttpURLConnection) url.openConnection();
          conn.setConnectTimeout(5000);
          conn.setRequestMethod("GET");
          int code = conn.getResponseCode();
          if(code == 200){
            InputStream is = conn.getInputStream();
            Bitmap bitmap = BitmapFactory.decodeStream(is);
            Message msg = Message.obtain();
            msg.what = SUCCESS;
            msg.obj = bitmap;
            handler.sendMessage(msg);
            is.close();
          }
        } catch (Exception e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
           Message msg = Message.obtain();
           msg.what = ERORR;
           handler.sendMessage(msg);
        }
      };
    }.start();
  }
}

至此五种数据存储全部实现。当然,实际开发中可能比这更复杂,会嵌入到别的知识点中,但数据操作无疑是最为基本的一步,是整体项目开发的基础。

您可能感兴趣的文章:Android开发笔记之: 数据存储方式详解在android开发中进行数据存储与访问的多种方式介绍Android 数据存储方式有哪几种Android编程中的5种数据存储方式Android使用文件进行数据存储的方法Android数据存储之SQLite使用四种Android数据存储方式android数据存储之文件存储方法详解Android数据存储之Android 6.0运行时权限下文件存储的思考Android系统的五种数据存储形式实例(一)


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android系统的五种数据存储形式实例(二)

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android系统的五种数据存储形式实例(二)

之前介绍了Android系统下三种数据存储形式,//www.jb51.net/article/99468.htm。今天补充介绍另外两种,分别是内容提供者和网络存储。有些人可能认为内存提供者和网络存储更偏向于对数据的操作而不是数据的存储,但这
2022-06-06

Android系统的五种数据存储形式实例(一)

Android系统有五种数据存储形式,分别是文件存储、SP存储、数据库存储、contentprovider 内容提供者、网络存储。其中,前四个是本地存储。存储的类型包括简单文本、窗口状态存储、音频视频数据、XML注册文件的各种数据。各种存储
2022-06-06

Android平台中实现数据存储的5种方式

本文介绍Android中的5种数据存储方式,具体内容如下 数据存储在开发中是使用最频繁的,在这里主要介绍Android平台中实现数据存储的5种方式,分别是: 1 使用SharedPreferences存储数据 2 文件存储数据 3
2022-06-06

Android App中各种数据保存方式的使用实例总结

少量数据保存之SharedPreferences接口实例 SharedPreferences数据保存主要是通过键值的方式存储在xml文件中 xml文件在data/此程序的包名/XX.xml。 格式:
2022-06-06

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录