Android炫酷应用300例读书笔记七

第7章文件和数据
199.使用JSONObject解析JSON字符串
书中是给了一个JSON格式的String,然后通过JSONObject去解析。

public class MainActivity extends AppCompatActivity{
    private static final String TAG = "MainActivity";
    private String mString = "{\"name\":\"AAA\",\"book\":\"BBB\"}";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        try {
            JSONTokener jsonTokener = new JSONTokener(mString);
            JSONObject jsonObject = (JSONObject) jsonTokener.nextValue();
            Log.d(TAG," name = " + jsonObject.getString("name") + " book = " + jsonObject.getString("book"));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    
}

运行结果如下:

D/MainActivity:  name = AAA book = BBB

200.使用JSONArray解析JSON字符串
书中是给了一个JSONArray格式的String,然后通过JSONObject去解析。

public class MainActivity extends AppCompatActivity{
    private static final String TAG = "MainActivity";
    private String mString = "[{\"name\":\"张三\",\"book\":\"AAA\"},{\"name\":\"李四\",\"book\":\"BBB\"}]";
            //"{\"name\":\"AAA\",\"book\":\"BBB\"}";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        try {
            JSONArray jsonArray = new JSONArray(mString);
            for (int i = 0; i < jsonArray.length(); i++){
                JSONObject jsonObject =  jsonArray.getJSONObject(i);
                Log.d(TAG," name = " + jsonObject.getString("name") + " book = " + jsonObject.getString("book"));
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

}

运行结果如下


image.png

201.使用JSONTokener解析JSON字符串

public class MainActivity extends AppCompatActivity{
    private static final String TAG = "MainActivity";
    private String mString = "大家系列:{\"name\":\"ABCD\",\"book\":\"EFGH\"}";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        try {
            JSONTokener jsonTokener = new JSONTokener(mString);
            Log.d(TAG,jsonTokener.nextString('G'));//读取G之前的字符

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

}

运行结果如下。

D/MainActivity: 大家系列:{"name":"ABCD","book":"EF

202.使用JsonReader解析JSON字符串

public class MainActivity extends AppCompatActivity{
    private static final String TAG = "MainActivity";
    private String mString = "[{\"name\":\"张三\",\"book\":\"AAA\"},{\"name\":\"李四\",\"book\":\"BBB\"}]";
    private String mInfo = "";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        try {
            JsonReader jsonReader = new JsonReader(new StringReader(mString));
            jsonReader.beginArray();
            while (jsonReader.hasNext()){
                jsonReader.beginObject();
                while (jsonReader.hasNext()){
                    String string = jsonReader.nextName();
                    if (string.equals("name")){
                        mInfo += "\n 作者" + jsonReader.nextString();
                    }else if (string.equals("book")){
                        mInfo += "\n 书名" + jsonReader.nextString();
                    }
                }
                jsonReader.endObject();
            }
            jsonReader.endArray();
            Log.d(TAG,"mInfo = " + mInfo);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

运行结果如下:


image.png

203.使用JSONStringer创建JSON字符串

public class MainActivity extends AppCompatActivity{
    private static final String TAG = "MainActivity";
    private String mString = "[{\"name\":\"张三\",\"book\":\"AAA\"},{\"name\":\"李四\",\"book\":\"BBB\"}]";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        try {
            JSONStringer jsonStringer = new JSONStringer();
            //object 和endObject表示一个{}  array 和 endArray表示一个[]
            jsonStringer.array();

            jsonStringer.object();
            jsonStringer.key("name");
            jsonStringer.value("张三");
            jsonStringer.key("book");
            jsonStringer.value("AAA");
            jsonStringer.endObject();

            jsonStringer.object();
            jsonStringer.key("name");
            jsonStringer.value("李四");
            jsonStringer.key("book");
            jsonStringer.value("BBB");
            jsonStringer.endObject();

            jsonStringer.object();
            jsonStringer.key("name");
            jsonStringer.value("王二");
            jsonStringer.key("book");
            jsonStringer.value("CCC");
            jsonStringer.endObject();

            jsonStringer.endArray();
            Log.d(TAG,jsonStringer.toString());
        } catch (JSONException ex) {
            throw new RuntimeException(ex);
        }
    }

}

运行结果如下

 D/MainActivity: [{"name":"张三","book":"AAA"},{"name":"李四","book":"BBB"},{"name":"王二","book":"CCC"}]

延伸阅读:
Android入门——数据解析之创建及使用JSON字符串(一)
https://blog.csdn.net/CrazyMo_/article/details/78297201
Android入门——数据解析之使用GSON解析JSON字符串(二)
https://blog.csdn.net/CrazyMo_/article/details/78518133

Json相关个人总结

首先来看什么是JSON。
//下面这段出自android编程权威指南。

JSON(JavaScript Object Notation)是近年流行开来的一种 数据格式,尤其适用于Web服务。Android提供了标准的org.json包,可以利用包里的一些类创建和解析JSON数据。Android开发者文档有其详细信息。要详细了解JSON数据格式,请访问其官方网站:http://json.org

这个简单了解一下就好了,接下来看api。
为了了解JSON数据,需要先找一些api接口。直接开放的免费接口还是比较少的,大多数需要注册账号然后申请。我找了一点,链接如下所示。
整理一些完全免费开放的API接口
https://blog.csdn.net/qq_41856814/article/details/89290195
干货集中营 API 文档
http://gank.io/api
玩Android 开放API
https://www.wanandroid.com/blog/show/2

其实还可以用tomcat自行搭建一个服务器。参考链接如下。
使用struts手动搭建一个自己的tomcat服务器,用来返回json数据
//www.greatytc.com/p/42665afd987f

这里先使用一下这个api:
https://www.wanandroid.com//hotkey/json
直接在浏览器中访问这个链接,得到如下json数据。

{"data":[{"id":6,"link":"","name":"面试","order":1,"visible":1},{"id":9,"link":"","name":"Studio3","order":1,"visible":1},{"id":5,"link":"","name":"动画","order":2,"visible":1},{"id":1,"link":"","name":"自定义View","order":3,"visible":1},{"id":2,"link":"","name":"性能优化 速度","order":4,"visible":1},{"id":3,"link":"","name":"gradle","order":5,"visible":1},{"id":4,"link":"","name":"Camera 相机","order":6,"visible":1},{"id":7,"link":"","name":"代码混淆 安全","order":7,"visible":1},{"id":8,"link":"","name":"逆向 加固","order":8,"visible":1}],"errorCode":0,"errorMsg":""}

直接得到的json数据可读性并不好,需要转换一下。
使用在线格式化工具,格式化一下。
https://www.sojson.com/

image.png

{
    "data": [{
        "id": 6,
        "link": "",
        "name": "面试",
        "order": 1,
        "visible": 1
    }, {
        "id": 9,
        "link": "",
        "name": "Studio3",
        "order": 1,
        "visible": 1
    }, {
        "id": 5,
        "link": "",
        "name": "动画",
        "order": 2,
        "visible": 1
    }, {
        "id": 1,
        "link": "",
        "name": "自定义View",
        "order": 3,
        "visible": 1
    }, {
        "id": 2,
        "link": "",
        "name": "性能优化 速度",
        "order": 4,
        "visible": 1
    }, {
        "id": 3,
        "link": "",
        "name": "gradle",
        "order": 5,
        "visible": 1
    }, {
        "id": 4,
        "link": "",
        "name": "Camera 相机",
        "order": 6,
        "visible": 1
    }, {
        "id": 7,
        "link": "",
        "name": "代码混淆 安全",
        "order": 7,
        "visible": 1
    }, {
        "id": 8,
        "link": "",
        "name": "逆向 加固",
        "order": 8,
        "visible": 1
    }],
    "errorCode": 0,
    "errorMsg": ""
}

204.使用JSONObject根据IP显示所在城市
2个知识点,1.通过api判断城市2.获取本机ip。
书上用的是新浪的判断城市的api,但是我试了一下无法访问。因此那部分略过。基本原理就是访问链接,然后解析返回的json数据,这些数据里面有城市的信息。
下面是获取本机ip的代码。

    /***
     * 使用WIFI时,获取本机IP地址
     * @param mContext
     * @return
     */
    public static String getWIFILocalIpAdress(Context mContext) {
      
        //获取wifi服务
        WifiManager wifiManager = (WifiManager)mContext.getSystemService(Context.WIFI_SERVICE);
        //判断wifi是否开启
        if (!wifiManager.isWifiEnabled()) {
        wifiManager.setWifiEnabled(true); 
        }
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();    
        int ipAddress = wifiInfo.getIpAddress();
        String ip = formatIpAddress(ipAddress);
        return ip;
    }  
    private static String formatIpAddress(int ipAdress) {    
      
         return (ipAdress & 0xFF ) + "." +    
        ((ipAdress >> 8 ) & 0xFF) + "." +    
        ((ipAdress >> 16 ) & 0xFF) + "." +    
        ( ipAdress >> 24 & 0xFF) ;
     }

参考链接:
Android系统信息获取 之七:获取IP地址和MAC地址
https://blog.csdn.net/netwalk/article/details/9821937

205.使用Gson将数组转换成JSON字符串
206.使用Gson解析JSON字符串
205和206合并一下,可以看下面的链接。
参考链接:
Android使用Google Gson实现JSON字符串和对象、对象数组之间相互转换
https://blog.csdn.net/xiaoyao20161314/article/details/72459518

其实android studio中还可以用插件去本地化json。
参考链接:
Android Json转对象本地快速测试
//www.greatytc.com/p/b47ab8db56ae

207.使用XmlPullParser解析城市天气数据
这里书上是用的聚合数据的天气预报接口,并且代码里给出了key,但是好像这个接口是要钱的,首次申请送500次。所以跳过本节。

208.采用SAX方式解析XML文件内容
参考链接:
android 如何使用SAX解析XML
https://blog.csdn.net/bzlj2912009596/article/details/80262191

209.使用Pattern根据正则表达式校验手机号码

public class MainActivity extends AppCompatActivity{
    private static final String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG," result = " + isMobile("1xxxx"));//这里传入一个手机号码
    }

    /**
     * 判断是否是手机号
     *
     * @param mobile
     * @return
     */
    public static boolean isMobile(String mobile) {
        // "[1]"代表第1位为数字1,"[358]"代表第二位可以为3、5、8中的一个,"\\d{9}"代表后面是可以是0~9的数字,有9位。
        String regex = "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\\d{8}$";
        Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
        Matcher m = p.matcher(mobile);
        return m.matches();
    }


}
D/MainActivity:  result = true

参考链接:
2018手机号码正则表达式
https://blog.csdn.net/github_36344730/article/details/79757676

210.使用SharedPreferences保存账户和密码
参考链接:
Android——登录界面、SharedPreferences实现记住密码等账户信息
https://blog.csdn.net/xuejingfu1/article/details/51638684

211.使用ListPreference读写单选按钮值
这是一个PreferenceActivity使用的知识点。这个类我还真的从来没有见过。
PreferenceActivity使用介绍
https://blog.csdn.net/ezconn/article/details/91452516

212.在代码中获取CheckBoxPreference值
这里的知识点是CheckBoxPreference的使用。
参考链接:
CheckBoxPreference--数据存储
https://blog.csdn.net/lovewlforever/article/details/27355067

213.通过PreferenceScreen跳转到Wifi设置
参考链接:
preferenceScreen 利用intent跳转activity
https://blog.csdn.net/hello_kate/article/details/43524381

214.使用Intent实现在Activity之间传递小图像
215.使用Intent在Activity之间传递图像和文本
216.使用Intent在Activity之间传递集合数据
217.在Intent传递数据时使用Bundle携带数组
218.使用Intent在Service和Activity之间传递数据

214-218小节由于是Intent的传递数据的基本使用,可以延伸一下另开一个专题,所以跳过。

219.使用FileInputStream和FileOutputStream读取和保存文本文件
参考链接:
Android中TXT文本文件写入与读取(总结)
https://blog.csdn.net/lpCrazyBoy/article/details/88354259

220.将浮雕风格的特效文字保存为图像文件
2个知识点,一个是是DrawingCache的使用,另一个是bitmap的存储。
书上的代码稍微有点问题,获取的bitmap是null。有可能是xml部分需要改一点,后面我稍微修改了一点java代码,最后代码如下。领android:background必须填ffffff,否则截屏会变黑。如果代码运行报错的话最好先写个ImageView判断一下bitmap是否能正常获取,再一步步判断问题所在。

先加入权限

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:gravity="center"
              android:orientation="vertical"
              >
  <TextView
       android:id="@+id/text_view"
       android:text="炫酷"
       android:textSize="40sp"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:background="#ffffff"/>


</LinearLayout>
public class MainActivity extends AppCompatActivity{
    private static final String TAG = "MainActivity";
    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = (TextView) findViewById(R.id.text_view);

        Bitmap bitmap = convertViewToBitmap(mTextView);
        try {
            Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    new ContentValues());
            OutputStream outputStream = getContentResolver().openOutputStream(uri);
            bitmap.compress(Bitmap.CompressFormat.JPEG,90,outputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static Bitmap convertViewToBitmap(View view){
    view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
        view.buildDrawingCache();
        Bitmap bitmap = view.getDrawingCache();
        return bitmap;
    }

}

参考链接:
Android View之DrawingCache的使用
//www.greatytc.com/p/3526bc69f287
Android使用View.getDrawingCache截取的图像变成黑底黑屏的解决方法备忘
https://blog.csdn.net/fengwusan/article/details/88617050

221.在SD卡上将Bitmap保存为PNG图像文件
参考链接:
Android把Bitmap保存为PNG图像文件的简单方法(同步)
https://blog.csdn.net/zhangphil/article/details/75090282

222.从手机相册中选择图像文件并裁剪头像
参考链接:
Android 从本地图库或拍照后裁剪图片并设置头像

223.在ListView上加载手机外存的图像文件
2个知识点,ContentProvider读取图像文件和ListView显示。
跳过。

224.使用DownloadManager下载网络文件
参考链接:
Android使用DownloadManager完成apk下载(适配到8.0)
//www.greatytc.com/p/ca2e82c8be7c

225.使用RandomAccessFile实现断点续传下载
参考链接:
RandomAccessFile实现断点续传
//www.greatytc.com/p/f4bc67f31005

226.使用HttpURLConnection下载图像文件
首先,找一个图片的下载链接。
随便百度找一个图片。


image.png

点击下载。这里我用的是chrome自带的下载,下载后如下图所示,会有下载链接。


image.png

复制链接地址,这个链接地址就是需要的url。
image.png

这个链接点进去就会下载图片。
https://image.baidu.com/search/down?tn=download&ipn=dwnl&word=download&ie=utf8&fr=result&url=http%3A%2F%2Fimage109.360doc.com%2FDownloadImg%2F2018%2F07%2F2207%2F139155100_23_20180722072723763.jpg&thumburl=https%3A%2F%2Fss1.bdstatic.com%2F70cFuXSh_Q1YnxGkpoWK1HF6hhy%2Fit%2Fu%3D204052842%2C882108833%26fm%3D26%26gp%3D0.jpg

public class MainActivity extends AppCompatActivity{
    private static final String TAG = "MainActivity";
    private String mUrlString = "https://image.baidu.com/search/down?tn=download&ipn=dwnl&word=download&ie=utf8&fr=result&url=http%3A%2F%2Fimage109.360doc.com%2FDownloadImg%2F2018%2F07%2F2207%2F139155100_23_20180722072723763.jpg&thumburl=https%3A%2F%2Fss1.bdstatic.com%2F70cFuXSh_Q1YnxGkpoWK1HF6hhy%2Fit%2Fu%3D204052842%2C882108833%26fm%3D26%26gp%3D0.jpg";
    private ImageView mImageView;
    private Handler mHandler = new Handler(){
        public void handleMessage(Message message){
            Bitmap bitmap = (Bitmap) message.obj;
            mImageView.setImageBitmap(bitmap);
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mImageView = (ImageView) findViewById(R.id.image_view);
        new Thread(){
            public void run(){
                try {
                    URL url = new URL(mUrlString);
                    HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
                    httpURLConnection.setConnectTimeout(5000);
                    int code = httpURLConnection.getResponseCode();
                    if (code == 200){
                        InputStream inputStream = httpURLConnection.getInputStream();
                        Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                        Message message = Message.obtain();
                        message.obj = bitmap;
                        mHandler.sendMessage(message);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        }.start();
    }
    

}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:gravity="center"
              android:orientation="vertical" >
    <ImageView
        android:id="@+id/image_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,123评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,031评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,723评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,357评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,412评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,760评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,904评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,672评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,118评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,456评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,599评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,264评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,857评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,731评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,956评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,286评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,465评论 2 348

推荐阅读更多精彩内容