Android配置文件分享和JSON数据生成与解析
Posted 中国思想史
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android配置文件分享和JSON数据生成与解析相关的知识,希望对你有一定的参考价值。
首先声明,我这里大体是讲的一个关于“android配置文件分享和JSON数据生成与解析”的整体流程,具体数据库中的数据根据读者自己的项目来安排,如果您看不大懂也请您原谅,毕竟我说了,我只是新手。其实关于数据库中的数据你只需要知道他们都是一个个对象,然后有各自的属性就行了,我们的关键在于JSON数据的生成与解析。
鉴于自己的是个博客新手,感觉自己的博客访问量有些少可能是因为自己确实知识匮乏,毕竟我早就说了,我不适合编程,但是没办法啊,我要去读个文学博士的话,怕是要遭人白眼了,故而以后的事情可以以后再说,当下还是要编程的,这也是没有办法的事情。好了,不多说了,办正事。
多说一句,代码片看起来有点小,所以显得乱,你可以自己复制下来,把它放大,自己研究,很容易就会看懂的。
首先是配置文件分享:
第一代码段:
//配置文件分享Function
private void shareConfiguration() {
// Get configuration data.
//这是配置文件的名字,文件是JSON类型的
String fileName = "configurationData" + System.currentTimeMillis() + ".json";
//这个是从数据库中取数据以便于写到配置文件中,后面还要说到
String configuration = mDBManager.getDataBaseAsJson();
// Create the temporal file within the private application folder,
//将上述从数据库中读取的数据写入到配置文件
tmpSharingFile = Utils.writeToSDFile(fileName, configuration);
if (tmpSharingFile == null) {
//如果配置文件中没有任何数据,就提示一个错误信息
Toast.makeText(this, getString(R.string.error_sharing_configuration), Toast.LENGTH_SHORT).show();
return;
}
//弹出一个分享对话框
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
//将配置文件数据放到分享数据流中
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(tmpSharingFile));
//这个是分享对话框标题
shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, getString(R.string.share_configuration));
//shareIntent.setType("application/json");
//这里是指定分享文件的类型,我们可以选择任意的二进制数据类型,以便于支持多种分享接口
shareIntent.setType("application/octet-stream");
//用于分享配置文件成功后,删除本地暂存的配置文件
startActivityForResult(Intent.createChooser(shareIntent, getResources().getText(R.string.send_to)), SHARING_RESULT_CODE);
}
第二代码段:
<span style="font-size:18px;"> @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == SHARING_RESULT_CODE) {
if (tmpSharingFile != null) {
tmpSharingFile.delete();
}
}
}</span>
第三代码段:
<span style="font-size:18px;"> /**
* Get the database as a json format.
*
* @return json containing the database.
*/
public synchronized String getDataBaseAsJson() {
JSONObject objJson = new JSONObject();
try {
// 用于存储所有Devices条目.
JSONArray jsonDevices = new JSONArray();
List<Device> devices = getAllDevicesList();//从数据库中查询所有的Device数据存储到列表中
for (int i = 0; i < devices.size(); i++) {
//遍历得到的Device数据列表
Device device = devices.get(i);
JSONObject deviceJson = new JSONObject();
//将Device的所有属性信息以键值对的形式放入deviceJson(JSONObject类型),在接收端会根据键(Key)来获取对应的值(Value)
deviceJson.put(KEY_DEVICE_ID, device.getDeviceID());
deviceJson.put(KEY_DEVICE_NAME, device.getName());
deviceJson.put(KEY_DEVICE_ASSOCIATED,1);
deviceJson.put(KEY_DEVICE_HASH, device.getDeviceHash());
deviceJson.put(KEY_DEVICE_APPEARANCE, device.getAppearance());
deviceJson.put(KEY_DEVICE_MODEL_LOW, device.getModelLow());
deviceJson.put(KEY_DEVICE_MODEL_HIGH, device.getModelHigh());
deviceJson.put(KEY_DEVICE_NUM_GROUPS, device.getNumGroups());
// 存储每个Device所属分组的ID组成的数组(int型)如{1,2,3}
JSONArray jsonGroups = new JSONArray();
int[] groups = device.getGroups();
for (int j = 0 ; j < groups.length; j++) {
jsonGroups.put(groups[j]);
}
deviceJson.put(KEY_DEVICE_GROUPS, jsonGroups);
deviceJson.put(KEY_DEVICE_AUTH_CODE, device.getAuthCode());
jsonDevices.put(deviceJson);
}
//将所有的Device条目jsonDevices(JSONArray类型)存储到objJson(JSONObject类型)中
objJson.put(KEY_DEVICES_LIST, jsonDevices);
//存储所有的分组数据
JSONArray jsonAreas = new JSONArray();
List<Area> areas = getAllAreaList();
for (int i = 0; i < areas.size(); i++) {
Area area = areas.get(i);
//存储每一条分组数据到areaJson同时将areaJson添加到jsonAreas中
JSONObject areaJson = new JSONObject();
areaJson.put(KEY_AREA_NAME, area.getName());
areaJson.put(KEY_AREA_ID, area.getAreaID());
jsonAreas.put(areaJson);
}
//将所有的Area条目 jsonAreas(JSONArray类型)存储到objJson(JSONObject类型)中
objJson.put(KEY_AREAS_LIST, jsonAreas);
}
catch (Exception e) {
return null;
}
//以字符串的形式返回objJson,用于生成本地的JSON文件,具体请见第一代码段
return objJson.toString();
}</span>
第四代码段:
<span style="font-size:18px;">/**
* Method to write text characters to file on SD card.
*
* @param filename
* @param text
* @return
*/
static public File writeToSDFile(String filename, String text) {
//获取外部存储介质的根目录
File root = android.os.Environment.getExternalStorageDirectory();
//获取根目录的绝对路径并在该路径下新建文件
File dir = new File(root.getAbsolutePath());
dir.mkdirs();
//指定新建文件的名称
File file = new File(dir, filename);
try {
//指定输出文件
FileOutputStream f = new FileOutputStream(file);
//打印数据工具类
PrintWriter pw = new PrintWriter(f);
//将text写入到文件file中
pw.println(text);
//将输出缓冲区的所有数据一次性写入,然后关闭文件输出流
pw.flush();
pw.close();
f.close();
}
catch (Exception e) {
e.printStackTrace();
return null;
}
//返回一个文件对象,用于后续操作,具体请见第一代码段中的tmpSharingFile
return file;
}
</span>
好了,经过上面的一系列操作,我们已经成功地把数据库中的Device和Area数据在本地生成了JSON文件,并通过调用第三方接口分享出去。那么我们如何来接受并解析JSON文件呢?不要着急,接下来我们还是用代码说话。
第五代码段:
//选择要导入到数据库中的JSON文件
private void pickFileToImport() {
//打开系统的文件管理功能
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
//intent.setType("file/*");
intent.setType("application/json");
startActivityForResult(intent, PICKFILE_RESULT_CODE);
}
第六代码段:
<span style="font-size:18px;"> @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICKFILE_RESULT_CODE && resultCode == Activity.RESULT_OK) {
//新Activity成功关闭并返回数据
if (data == null || data.getData() == null) {
//如果返回数据为空,则给出错误提示信息
Toast.makeText(getApplicationContext(), getString(R.string.error_opening_file), Toast.LENGTH_SHORT).show();
return;
}
//根据得到的data参数获取到data中存储的文件路径(文件全称)
Uri uri = data.getData();
//根据data存储的路径新建一个文件file对象
File file = new File(uri.getPath());
// Check the extension of the file. App only accept .json extensions.
if (!Utils.getFileExtension(file).equalsIgnoreCase(".json")) {
//如果文件file的类型不是.JSON,则给出错误提示信息,具体请见第七代码段
Toast.makeText(this, getString(R.string.invalid_file_extension), Toast.LENGTH_SHORT).show();
// no continue.
return;
}
//Start reading a file...开始读取文件数据
//为什么使用StringBuilder而不是StringBuffer可以参考我的另一篇博客 http://blog.csdn.net/songkai320/article/details/51823246
final StringBuilder json = new StringBuilder();
try {
//读取文件数据并放到缓冲区
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while ((line = br.readLine()) != null) {
//从缓冲区读取数据并存储到json对象中
json.append(line);
}
br.close();
}
catch (IOException e) {
Toast.makeText(getApplicationContext(), getString(R.string.error_opening_file), Toast.LENGTH_SHORT).show();
return;
}
// end reading file
// Confirm replacing database.
//将json(StringBuilder类型)转换为字符串格式
mImportedJson = json.toString();
if (mEditMode) {
//如果处于编辑修改模式,则用导入的数据覆盖当前的数据,具体请见第八代码段
confirmReplacingDatabase(mImportedJson);
}
else {
//如果处于新建模式,则直接将数据导入到本地数据库中
DialogMaterial infoDialog = new DialogMaterial(this, getString(R.string.import_notify_title), getString(R.string.import_notify));
infoDialog.addCancelButton("OK");
infoDialog.show();
}
}
}</span>
第七代码段:
<span style="font-size:18px;">/**
* Get the extension of a file.
*
* @param file
* @return extension.
*/
static public String getFileExtension(File file) {
String name = file.getName();
try {
return name.substring(name.lastIndexOf("."));
}
catch (Exception e) {
return "";
}
}</span>
第八代码段:
<span style="font-size:18px;">private void confirmReplacingDatabase(final String json) {
//弹出一个对话框问你是不是要覆盖当前数据,点击“是”开始导入JSON数据
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(getString(R.string.confirm_replacing_db));
builder.setCancelable(false);
builder.setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
new Thread(new Runnable() {
@Override
public void run() {
//覆盖原来的数据,具体请见第九代码段
replaceDatabase(json);
}
}).start();
}
});
builder.setNegativeButton(getString(R.string.no), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}</span>
第九代码段:
<span style="font-size:18px;">private void replaceDatabase(String json) {
//首先从JSON字符串中得到Device列表,这也是JSON文件解析的关键地方,鉴于这个属性太多,我们选择用<span style="font-family: Arial, Helvetica, sans-serif;">Area的解析作为示例,具体请见第十代码段</span>
List<Device> devices = mDBManager.getListDevicesByJson(json, mPlace.getId());
//同上,只不过是Area列表数据
List<Area> areas = mDBManager.getListAreasByJson(json, mPlace.getId());
if (devices == null || areas == null) {
runOnUiThread(new Runnable() {
public void run() {
//如果从JSON字符串中取到的数据为null,那么就给出错误提示信息
Toast.makeText(DetailPlaceActivity.this, R.string.error_importing_db, Toast.LENGTH_SHORT).show();
}
});
}
else {
// 首先删除所有的当前Device数据,以便于导入新的数据来替代
mDBManager.removeAllDevicesByPlaceId(mPlace.getId());
// 然后删除所有的当前Area数据,以便于导入新的数据来替代
mDBManager.removeAreaOfPlaceWithId(mPlace.getId());
for (int i = 0; i < devices.size(); i++) {
//将从JSON字符串中解析得到的Device数据一一添加到本地数据库
mDBManager.createOrUpdateDevice(devices.get(i));
}
for (int i = 0; i < areas.size(); i++) {
//将从JSON字符串中解析得到的Area数据一一添加到本地数据库
mDBManager.createOrUpdateArea(areas.get(i));
}
runOnUiThread(new Runnable() {
public void run() {
//弹出新数据导入成功的提示信息
Toast.makeText(DetailPlaceActivity.this, R.string.db_imported, Toast.LENGTH_SHORT).show();
}
});
//更新数据库
mDeviceManager.refreshInfo();
}
}
</span>
第十代码段:
<span style="font-size:18px;"> /**
* Create a list of Area objects from JSON.
* @param json JSON string containing the description of the areas.
* @param placeId The place id to use for the areas.
* @return A list of Area objects.
*/
public synchronized List<Area> getListAreasByJson(String json, int placeId) {
List<Area> areas = new ArrayList<>();
try {
//通过JSON字符串生成一个JSONObject对象,其实和生成JSON文件的过程大致相反
JSONObject jsonObj = new JSONObject(json);
//根据键(Key)KEY_AREAS_LIST获取到Area列表的数据jsonArray
JSONArray jsonArray = jsonObj.getJSONArray(KEY_AREAS_LIST);
for (int areasIndex = 0; areasIndex < jsonArray.length(); areasIndex++) {
Area area = new Area();
//从jsonArray中根据Area的属性每次取出一组数据赋给新建的area对象并添加到areas(List<Area>类型)中
String areaName = jsonArray.getJSONObject(areasIndex).getString(KEY_AREA_NAME);
area.setName(areaName);
int areaId = jsonArray.getJSONObject(areasIndex).getInt(KEY_AREA_ID);
area.setAreaID(areaId);
area.setPlaceID(placeId);
areas.add(area);
}
}
catch (JSONException e) {
return null;
}
//返回所有的Area数据,以便于插入到本地数据库,具体见第九代码段
return areas;
}</span>
好了,到此就把“Android配置文件分享和JSON数据生成与解析”的流程讲解完毕。感谢您的阅读。
以上是关于Android配置文件分享和JSON数据生成与解析的主要内容,如果未能解决你的问题,请参考以下文章
Android Studio 解析json文件出现中文乱码解决方法
GeoJson的生成与解析,JSON解析,Java读写geojson,geotools读取shp文件,Geotools中Geometry对象与GeoJson的相互转换