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数据生成与解析的主要内容,如果未能解决你的问题,请参考以下文章

ProtocolBuffer在Android端的解析

Android Studio 解析json文件出现中文乱码解决方法

Android 中解析 JSON

GeoJson的生成与解析,JSON解析,Java读写geojson,geotools读取shp文件,Geotools中Geometry对象与GeoJson的相互转换

Json的生成和解析

千万不要用JSON作配置文件