1. 程式人生 > >每日一記—獲取Bing每一日一圖實現Android歡迎頁(二)

每日一記—獲取Bing每一日一圖實現Android歡迎頁(二)

日期2018.9.12

第二部分:獲取bing每日一圖

通過訪問   http://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=5&mkt=zh-CN  可以得到一組json資料,如下:

{"images":
[{"startdate":"20180911",
"fullstartdate":"201809111600",
"enddate":"20180912",
"url":"/az/hprichbg/rb/BlackBrowed_ZH-CN11903207028_1920x1080.jpg",
"urlbase":"/az/hprichbg/rb/BlackBrowed_ZH-CN11903207028",
"copyright":"回到福克蘭群島的黑眉信天翁 (© Cultura RM/Alamy)",
"copyrightlink":"http://www.bing.com/search?q=%E9%BB%91%E7%9C%89%E4%BF%A1%E5%A4%A9%E7%BF%81&form=hpcapt&mkt=zh-cn",
"title":"",
"quiz":"/search?q=Bing+homepage+quiz&filters=WQOskey:%22HPQuiz_20180911_BlackBrowed%22&FORM=HPQUIZ",
"wp":true,
"hsh":"12948b177d0c26492dcb1049700602ea",
"drk":1,"top":1,"bot":1,"hs":[]},
{"startdate":"20180910",
"fullstartdate":"201809101600",
"enddate":"20180911",
"url":"/az/hprichbg/rb/ShinjukuKiku_ZH-CN8446848393_1920x1080.jpg",
"urlbase":"/az/hprichbg/rb/ShinjukuKiku_ZH-CN8446848393",
"copyright":"管物菊,日本東京都新宿區 (© I love Photo and Apple./Getty images)",
"copyrightlink":"http://www.bing.com/search?q=%E7%AE%A1%E7%89%A9%E8%8F%8A&form=hpcapt&mkt=zh-cn",
"title":"","quiz":"/search?q=Bing+homepage+quiz&filters=WQOskey:%22HPQuiz_20180910_ShinjukuKiku%22&FORM=HPQUIZ",
"wp":true,
"hsh":"c79ceca8823a08c1c93373f4b26c9996",
"drk":1,"top":1,"bot":1,"hs":[]},
{"startdate":"20180909",
"fullstartdate":"201809091600",
"enddate":"20180910",
"url":"/az/hprichbg/rb/Honeycomb_ZH-CN7204448210_1920x1080.jpg",
"urlbase":"/az/hprichbg/rb/Honeycomb_ZH-CN7204448210",
"copyright":"蜂巢 (© Heidi and Hans-Juergen Koch/Minden Pictures)",
"copyrightlink":"http://www.bing.com/search?q=%E8%9C%82%E5%B7%A2&form=hpcapt&mkt=zh-cn",
"title":"",
"quiz":"/search?q=Bing+homepage+quiz&filters=WQOskey:%22HPQuiz_20180909_Honeycomb%22&FORM=HPQUIZ",
"wp":true,
"hsh":"956060a94d566e18964ea6aff9a7a2aa",
"drk":1,"top":1,"bot":1,"hs":[]},
{"startdate":"20180908",
"fullstartdate":"201809081600",
"enddate":"20180909",
"url":"/az/hprichbg/rb/RoyalOntarioMuseum_ZH-CN10362892998_1920x1080.jpg",
"urlbase":"/az/hprichbg/rb/RoyalOntarioMuseum_ZH-CN10362892998",
"copyright":"皇家安大略博物館,加拿大多倫多 (© Ken Straiton/Aurora Photos)",
"copyrightlink":"http://www.bing.com/search?q=%E7%9A%87%E5%AE%B6%E5%AE%89%E5%A4%A7%E7%95%A5%E5%8D%9A%E7%89%A9%E9%A6%86&form=hpcapt&mkt=zh-cn",
"title":"",
"quiz":"/search?q=Bing+homepage+quiz&filters=WQOskey:%22HPQuiz_20180908_RoyalOntarioMuseum%22&FORM=HPQUIZ",
"wp":false,
"hsh":"ed4c961d60ff9e9ebc17f94a4fa5e8cb",
"drk":1,"top":1,"bot":1,"hs":[]},
{"startdate":"20180907",
"fullstartdate":"201809071600",
"enddate":"20180908",
"url":"/az/hprichbg/rb/TrinityLibrary_ZH-CN10332583093_1920x1080.jpg",
"urlbase":"/az/hprichbg/rb/TrinityLibrary_ZH-CN10332583093",
"copyright":"都柏林三一學院圖書館,愛爾蘭 (© Nigel Hicks/Robert Harding/Aurora Photos)",
"copyrightlink":"http://www.bing.com/search?q=%E4%B8%89%E4%B8%80%E5%AD%A6%E9%99%A2%E5%9B%BE%E4%B9%A6%E9%A6%86&form=hpcapt&mkt=zh-cn",
"title":"",
"quiz":"/search?q=Bing+homepage+quiz&filters=WQOskey:%22HPQuiz_20180907_TrinityLibrary%22&FORM=HPQUIZ",
"wp":false,
"hsh":"e5b5bf66170be8116ecd6a6f73fb1e1e",
"drk":1,"top":1,"bot":1,"hs":[]}],
"tooltips":{
"loading":"正在載入...",
"previous":"上一個影象",
"next":"下一個影象",
"walle":"此圖片不能下載用作桌布。",
"walls":"下載今日美圖。僅限用作桌面桌布。"}}

我們看到得到JSON資料中  每個組內都一個url屬性,即"url":"/az/hprichbg/rb/BlackBrowed_ZH-CN11903207028_1920x1080.jpg",我們通過這個URL就可以得到當前這個組裡的圖片,需要注意的事,這個URL缺少網址的前半部分,訪問的時候需要加上“http://www.bing.com”,即網址為:http://www.bing.com/az/hprichbg/rb/BlackBrowed_ZH-CN11903207028_1920x1080.jpg。那麼需要用到的邏輯程式碼就清楚了,第一步是獲取到這個JSON資料;第二步是解析這個JSON資料;第三步是將得到的圖片URL轉成bitmap;第四步是將轉化的bitmap賦值給背景圖片,並將這個bitmap儲存在本地,這樣可以在再次開啟程式的時候直接訪問本地圖片,不必再重複下載。

第一步:獲取JSON資料

這裡我使用的是HttpURLConnection進行的連結,程式碼如下:

    private String getData(String path){
        String data="";
        try{
            URL url = new URL(path);
            HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
            urlConn.setConnectTimeout(5000);
            urlConn.connect();
            if (urlConn.getResponseCode() == 200) {
                data = readStream(urlConn.getInputStream());
                Log.i("TAG", "請求成功");
            } else {
                Log.i("TAG", "資料請求失敗");
            }
            urlConn.disconnect();
        }catch (Exception e){
            e.printStackTrace();
        }
        return data;
    }

    private String readStream(InputStream inputStream) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, len);
            outputStream.flush();
        }
        outputStream.close();
        inputStream.close();
        return outputStream.toString();
    }

第二步:解析JSON資料,得到圖片URL

通過觀察之前得到的JSON資料,我們可以看出,這組資料裡包含了多個URL,也就是說存在多個日期的圖片,而我們想得到的是當天日期的圖片,因此,觀察可以看出,第一個URL是最新的圖片,因此在得到第一個URL資料的時候,就將這個URL返回就好了,無需再判斷其他的URL,程式碼如下:

    private String resolveData(String data){
        String url="";
        try{
            JSONArray jsonArray=new JSONObject(data).getJSONArray("images");
            for (int i=0;i<jsonArray.length();i++){
                JSONObject jsonObject = (JSONObject)jsonArray.get(i);
                if (jsonObject.has("url")){
                    url=jsonObject.getString("url");
                    break;
                }
            }
        }catch (JSONException e){
            e.printStackTrace();
        }
        return url;
    }

第三步:將圖片URL轉化為bitmap

注意在URL前面加上“http://www.bing.com”,程式碼如下:(這裡有一個問題,目前沒有解決,哪位高手給指點一下:就是這個BitmapFactory.decodeStream()獲取的圖片是變形的,如何獲取到適應螢幕,並且不變形的方法呢?

    private Bitmap getBitmap(String path) throws IOException {
        URL url = new URL("http://www.bing.com"+path);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(5000);
        conn.setRequestMethod("GET");
        if (conn.getResponseCode() == 200) {
            InputStream inputStream = conn.getInputStream();
            DisplayMetrics dm = getResources().getDisplayMetrics();//獲得螢幕的寬度和高度
            Bitmap bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeStream(inputStream), dm.widthPixels, dm.heightPixels, true);
            conn.disconnect();
            return bitmap;
        }
        conn.disconnect();
        return null;
    }

第四步:賦值給背景圖片,並將bitmap儲存在本地

這步就是要獲取圖片了,因此需要呼叫前三步中所有的函式,所以特別需要注意的是,在Android4.0以後,所有關於網路方面的操作都不能在主執行緒了(我們訪問bing的時候用到了INTERNET許可權),所以這裡使用了一個AsyncTask;並且由於在本地沒有圖片而載入圖片的時候,根據網速的不同,會造成介面的等待,因此加入了一個ProgressDialog,具體程式碼如下:

   class DownImgAsyncTask extends AsyncTask<String,Void,Bitmap> {
        @Override
        protected Bitmap doInBackground(String... strings) {
            try{
                Bitmap b=getBitmap(resolveData(getData(strings[0])));
                return b;
            }catch (IOException e){
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            progressDialog.show();
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            if (bitmap!=null){
                iv_background.setImageBitmap(bitmap);
                //儲存到本地
                CutPictureUtils.saveImageToGallery(SplashActivity.this,bitmap);
            }
            progressDialog.dismiss();
        }

        @Override
        protected void onProgressUpdate(Void... values) {
            super.onProgressUpdate(values);
        }
    }

儲存到本地的函式程式碼如下:

    public static void saveImageToGallery(Context context, Bitmap bmp) {
        // 首先儲存圖片
        File appDir = new File(Environment.getExternalStorageDirectory(), "crazystudy");
        if (!appDir.exists()) {
            appDir.mkdir();
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");// HH:mm:ss
//獲取當前時間
        Date date = new Date(System.currentTimeMillis());
        String fileName = simpleDateFormat.format(date) + ".jpg";
        File file = new File(appDir, fileName);
        try {
            FileOutputStream fos = new FileOutputStream(file);
            bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            fos.flush();
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

//        // 其次把檔案插入到系統圖庫
//        try {
//            MediaStore.Images.Media.insertImage(context.getContentResolver(),
//                    file.getAbsolutePath(), fileName, null);
//        } catch (FileNotFoundException e) {
//            e.printStackTrace();
//        }
//        // 最後通知相簿更新
//        context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + file.getPath())));
    }

現在我們可以呼叫這個DownImgAsyncTask來完成我們歡迎頁的製作了,在《每日一記—獲取Bing每一日一圖實現Android歡迎頁(一)》中的“獲取bing背景圖片”預留位置,加入如下程式碼:

        if(AnalysisUtils.isFolderExists("/sdcard/crazystudy/")){
            if (AnalysisUtils.fileIsExists(imgUri.getPath())){
                // 顯示出來
                CutPictureUtils cutPictureUtils=new CutPictureUtils(SplashActivity.this,
                        "");
                iv_background.setImageBitmap(cutPictureUtils.decodeUriAsBitmap(imgUri));
            }else {
                progressDialog = new ProgressDialog(this);
                progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
                progressDialog.setMessage("載入中");
                progressDialog.setCancelable(false);
                //獲取背景圖片
                String path = "http://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=5&mkt=zh-CN";
                new DownImgAsyncTask().execute(path);
            }
        }

這樣歡迎頁就完美的做好了,下面是效果圖: