基于Android的天氣APP

多知天氣

前言

項目:https://github.com/w77996/Weather

多知天氣,代碼寫的不咋的,主要是給大家學習一下。有些東西也是借鑒別人的主要借鑒的是別人的UI,因為我寫UI太難看了TAT,我自己都看不下去。

項目主要是12月23日開始建立,春節半個多月回家了,就沒有寫了。三月初完成了整個項目。耗時近兩個月。平時在公司也就做點測試的任務,開發的任務還得等到畢業后才有TAT不知道畢業后會不會被留下,所以也是練練手。基于Rxjava+Retrofif+Ok之后也寫了一個是http+Mvp的閱讀類APP,鏈接在這里:HiReader,項目還沒有完全寫完,一直在更新,主要是自己學習一些主流的東西。


感謝開源

看別人的代碼慢慢學習,你會看到自己的成長的~
現在的我看這個畢業設計項目會覺得沒有當初想的那么難了,可以用更高的效率,更好的方式去實現這個項目。

借鑒過的項目

就看天氣

高仿雅虎天氣

還有郭神的第二行代碼,不解釋

開源框架


功能

  1. 第一次打開APP引導頁,緩沖加載
  2. 天氣信息的顯示
  3. 廣告,推送
  4. 桌面小工具
  5. 新聞資訊的查看
  6. 藍牙串口傳輸溫度

那時候還不大會使用Gson,簡直就是Android開發的敗筆呀~傻乎乎的自己去解析近千的json信息,也是醉了。

準備

易源數據中的天氣Json如果請求的是15天的Json數據那有近千行,所以取自己有用的。

  • 開發環境:Android studio
  • 數據獲取:易源數據SDK

幫助工具

Json在線解析

易源數據官網


Json數據分析

image

這么多Json,細思極恐啊~
不過我們一步步來分析,key的作用可以看易源的文檔。

  1. cityInfo 城市信息
  2. time 時間
  3. now 現在的天氣
  4. f1~f6 近一星期的天氣預報信息
  5. alarmList 預警信息
  6. hourDataList 半小時更新一次的天氣信息
  7. aqi 空氣質量

天氣封裝

在目錄下新建com.weather.entity

其實覺得Gson挺好用的……
那我為何不用Gson呢。。。因為那時候還不會用@Serializedname,易源數據的json竟然還有用數字開頭的key ┭┮﹏┭┮

然后經過了一番的倒騰,終于一個個把數據給對上了= =,當做自己解析json數據的練手吧

網絡請求

主要是用okhttp,用到的是郭神的幾行代碼

 public static void sendOkHttpRequest(String address, okhttp3.Callback callback) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url(address).build();
        client.newCall(request).enqueue(callback);
    }
    

直接傳入地址就請求到數據了,

不過這邊有個坑!!
有個坑!!!

有個坑!!!

重要的事情所三遍

在請求后不能直接使用response.body().string(),要緩存一下才能使用,不然為空。

  //使用okhttp的封裝進行請求
        HttpUtil.sendOkHttpRequest(weatherUrl, new Callback() {
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                //這里有坑
                String responseText = response.body().string();

數據庫

本人數據庫超級爛,不過不算渣渣,還是能寫點東西,數據庫我設計的十分簡單,只有兩個重要的屬性,就是城市名和json數據,為的是在無網絡狀態下從數據庫直接獲取到json數據,解析后顯示到界面上。
框架的話本來打算用GreenDao的,不過后面改成LitePal了。

public class WeatherDB extends DataSupport {
    public int id;
    public String mCityName;
    public String mJsonData;
    ...
    

廣告,推送

廣告用的是有米廣告,直接對著SDK把代碼加進去就好了,想用騰訊的廣告,但是打電話給我問我有沒營業執照。。。。暈,沒有所以沒有審核通過。

推送使用的是極光推送,也是直接使用SDK,本來使用的是BOMB的,但是Bomb SDK中的okhttp和我自己的依賴起沖突了,而且還有一些機子無法推送成功,所以最后改成了極光推送,這都是血淋淋的坑啊,一步步踩過來簡直吐血。

    //廣告條初始化
        View bannerView = BannerManager.getInstance(WeatherActivity.this)
                .getBannerView(WeatherActivity.this, new BannerViewListener() {
                    @Override
                    public void onRequestSuccess() {}
                    @Override
                    public void onSwitchBanner() {}
                    @Override
                    public void onRequestFailed() {}
                });
        // 獲取要嵌入廣告條的布局
        LinearLayout bannerLayout = (LinearLayout) findViewById(R.id.ll_banner);
        // 將廣告條加入到布局中
        bannerLayout.addView(bannerView);

嵌入廣告就是這么簡單暴力,但是建議用積分墻,我這個是廣告條。。。。。

因為。。。
他們廣告條好像沒啥廣告。。。可能在實際中顯示不出來,不過在初始化時使用測試廣告的話那就可以看到了。

城市選擇

這里推薦別人寫的一個依賴,直接傳送門 CityPicker

用的是高德地圖定位


image
image

桌面小工具

這方面我需要學習的東西還有很多的,開啟服務在后臺更新,想想后期如果能加入Rxjava,看看能不能優化一些操作,不過在使用Glide加載圖片到AppWidget時需要獲取到ImageView控件,所以有折騰了一下。


image
image
   //通過APPWIdgetTarget獲取到Image控件
                 mAppWidgetTarget =new AppWidgetTarget(getApplicationContext(),mRemoteViews,R.id.appwiget_picture,mAppwidgetId);
                Glide.with(getApplicationContext()).load(weatherBean.getmNowWeatherBean().getmWeather_Pic()).asBitmap().into(mAppWidgetTarget);

藍牙和單片機通信模塊

因為本人學過嵌入式開發,在機緣巧合的時候接觸了Android,所以現在做Android開發,單片機上使用的是DS18B20溫度傳感器,藍牙是HC-05,通過串口進行溫度傳輸,不要覺得很難,其實很簡單,嗯,說笑的,基礎好就很簡單啦,代碼并不多,曾經試過一次返回數據一直都是亂碼,找了一個星期的問題都沒找到,最后發現是波特率的問題,太感動了,傳送門

界面

進入APP加載界面,淡入淡出效果,弱引用持有Activity對象,文字動畫效果


緩沖界面
緩沖界面
  //activity切換的淡入淡出效果
       overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
       
//弱引用的使用
 private static class SwitchHandler extends Handler {
        private WeakReference<SplashActivity> mWeakReference;

        SwitchHandler(SplashActivity activity) {
            mWeakReference = new WeakReference<SplashActivity>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            SplashActivity activity = mWeakReference.get();
            if (activity != null) {
                WeatherActivity.launch(activity);
                activity.finish();
            }
        }
    }

主界面

image
image

這邊其實沒有按照Material design的要求透明化狀態欄,主界面填充整個手機屏幕,通過計算手機屏幕總高度,減去狀態欄的高度和ActionBar的高度,得出了主界面視圖的高度,就做到了在任何分辨率下都只顯示這樣的界面的效果(原諒我這種拗口的表達,你懂就好哈哈哈哈~~)

  /**
     * 獲取手機屏幕高度
     *
     * @param context
     * @return
     */
    public static int getDisplayHeight(Context context) {
        WindowManager wm = (WindowManager) context
                .getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics dm = new DisplayMetrics();
        // 獲取屏幕信息
        wm.getDefaultDisplay().getMetrics(dm);
        return dm.heightPixels;
    }

    /**
     * 獲取手機屏幕寬度
     *
     * @param context
     * @return
     */
    public static int getDisplayWidth(Context context) {
        WindowManager wm = (WindowManager) context
                .getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics dm = new DisplayMetrics();
        // 獲取屏幕信息
        wm.getDefaultDisplay().getMetrics(dm);
        return dm.widthPixels;
    }

    /**
     * 反射方法獲取狀態欄高度
     *
     * @param context
     * @return
     */
    public static int getStatusBarHeight(Context context) {
        int statusBarHeight = 20;
        try {
            Class<?> _class = Class.forName("com.android.internal.R$dimen");
            Object object = _class.newInstance();
            Field field = _class.getField("status_bar_height");
            int restult = Integer.parseInt(field.get(object).toString());
            statusBarHeight = context.getResources().getDimensionPixelSize(
                    restult);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // Toast.makeText(getActivity(), "StatusBarHeight = " + statusBarHeight,
        // Toast.LENGTH_SHORT).show();
        return statusBarHeight;
    }

    /**
     * 獲取?attr/actionBarSize高度
     *
     * @param context
     * @return
     */
    public static int getActionBarSize(Context context) {
        TypedValue typedValue = new TypedValue();
        context.getTheme().resolveAttribute(R.attr.actionBarSize, typedValue, true);
        int actionBarHeight = TypedValue.complexToDimensionPixelSize(typedValue.data, context.getResources().getDisplayMetrics());
        return actionBarHeight;
    }
        // mNowWeatherHeight高度=屏幕高度-標題欄高度-狀態欄高度
        mNowWeatherHeight = SystemUtils.getDisplayHeight(mContext) - SystemUtils.getActionBarSize(mContext) - SystemUtils.getStatusBarHeight(mContext);

每半小時更新的數據list和未來天氣預報

這邊是RecyclerView,在繪制每個Item的時候也是計算了屏幕的寬度,每個item占屏幕的1/5,所以在所有分辨率下都只呈現五個Item

image
image

空氣指數和生活指數

UI 很多都是從Android Studio中的Vetor assert里面找的,大家也可以去找找適合自己的UI,還有阿里的iconfont阿里巴巴矢量圖標庫

image
image

城市編輯界面

背景Activity半透明,填充屏幕,listview側滑刪除

進入Activity后從數據庫中獲取到數據,然后顯示到listview中,進行操作后再主界面的onActivityResult中重新獲取數據庫中的內容,更新UI.

image
image
//側滑刪除
SwipeMenuCreator creator = new SwipeMenuCreator() {
            @Override
            public void create(SwipeMenu menu) {
                SwipeMenuItem openItem = new SwipeMenuItem(
                        getApplicationContext());
                SwipeMenuItem deleteItem = new SwipeMenuItem(
                        getApplicationContext());
                deleteItem.setBackground(new ColorDrawable(Color.rgb(0xF9,
                        0x3F, 0x25)));
                deleteItem.setWidth(dp2px(60));
                deleteItem.setIcon(R.drawable.ic_delete);
                menu.addMenuItem(deleteItem);

            }
        };
        mCityEditListview.setMenuCreator(creator);
        mCityEditListview.setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(int position, SwipeMenu menu, int index) {
                switch (index) {
                    case 0:
                        // open
                        Toast.makeText(getApplicationContext(), position + " menu click", Toast.LENGTH_SHORT).show();
                        if(mCityList.size()>1){
                            CityRmoveThread cityRmoveThread = new CityRmoveThread(mCityList.get(position).getmCityName());
                            cityRmoveThread.start();
                            mCityList.remove(position);
                            mCityEditListAdapter.notifyDataSetChanged();
                        }else{
                            Toast.makeText(getApplicationContext(), position + " 親,刪除了你看啥?", Toast.LENGTH_SHORT).show();
                        }
                        break;
                }
                // false : 會關閉菜單; true :不會關閉菜單
                return false;
            }
        });

新聞,笑話,美圖

這個模塊寫的說實話我自己都看不下去了,那時候為了趕進度,,哎,意思一下。用的是sharepreference進行很簡單的存儲。嗯,就是這樣的

總結

僅供參考,不得用于商業項目,如果覺得對你有幫助,給個Star吧親~
在寫項目的時候寫了好多細節,都忘了很多了,還是很用心去處理一些問題的~
還有引導頁設計的不是很好,是直接扣網絡上的圖片,到第三個界面的時候點擊一下就可以進去了~
謝謝觀看

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,786評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,656評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,697評論 0 379
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,098評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,855評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,254評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,322評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,473評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,014評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,833評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,016評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,568評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,273評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,680評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,946評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,730評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,006評論 2 374

推薦閱讀更多精彩內容