基于Android的天氣APP

多知天氣

前言

項(xiàng)目:https://github.com/w77996/Weather

多知天氣恒序,代碼寫的不咋的磕蛇,主要是給大家學(xué)習(xí)一下以政。有些東西也是借鑒別人的主要借鑒的是別人的UI,因?yàn)槲覍慤I太難看了TAT,我自己都看不下去膛檀。

項(xiàng)目主要是12月23日開(kāi)始建立,春節(jié)半個(gè)多月回家了娘侍,就沒(méi)有寫了咖刃。三月初完成了整個(gè)項(xiàng)目。耗時(shí)近兩個(gè)月憾筏。平時(shí)在公司也就做點(diǎn)測(cè)試的任務(wù)嚎杨,開(kāi)發(fā)的任務(wù)還得等到畢業(yè)后才有TAT不知道畢業(yè)后會(huì)不會(huì)被留下,所以也是練練手氧腰】某保基于Rxjava+Retrofif+Ok之后也寫了一個(gè)是http+Mvp的閱讀類APP,鏈接在這里:HiReader容贝,項(xiàng)目還沒(méi)有完全寫完自脯,一直在更新,主要是自己學(xué)習(xí)一些主流的東西斤富。


感謝開(kāi)源

看別人的代碼慢慢學(xué)習(xí)膏潮,你會(huì)看到自己的成長(zhǎng)的~
現(xiàn)在的我看這個(gè)畢業(yè)設(shè)計(jì)項(xiàng)目會(huì)覺(jué)得沒(méi)有當(dāng)初想的那么難了,可以用更高的效率满力,更好的方式去實(shí)現(xiàn)這個(gè)項(xiàng)目焕参。

借鑒過(guò)的項(xiàng)目

就看天氣

高仿雅虎天氣

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

開(kāi)源框架


功能

  1. 第一次打開(kāi)APP引導(dǎo)頁(yè),緩沖加載
  2. 天氣信息的顯示
  3. 廣告叠纷,推送
  4. 桌面小工具
  5. 新聞資訊的查看
  6. 藍(lán)牙串口傳輸溫度

那時(shí)候還不大會(huì)使用Gson,簡(jiǎn)直就是Android開(kāi)發(fā)的敗筆呀~傻乎乎的自己去解析近千的json信息刻帚,也是醉了。

準(zhǔn)備

易源數(shù)據(jù)中的天氣Json如果請(qǐng)求的是15天的Json數(shù)據(jù)那有近千行涩嚣,所以取自己有用的崇众。

  • 開(kāi)發(fā)環(huán)境:Android studio
  • 數(shù)據(jù)獲取:易源數(shù)據(jù)SDK

幫助工具

Json在線解析

易源數(shù)據(jù)官網(wǎng)


Json數(shù)據(jù)分析

image

這么多Json,細(xì)思極恐啊~
不過(guò)我們一步步來(lái)分析航厚,key的作用可以看易源的文檔顷歌。

  1. cityInfo 城市信息
  2. time 時(shí)間
  3. now 現(xiàn)在的天氣
  4. f1~f6 近一星期的天氣預(yù)報(bào)信息
  5. alarmList 預(yù)警信息
  6. hourDataList 半小時(shí)更新一次的天氣信息
  7. aqi 空氣質(zhì)量

天氣封裝

在目錄下新建com.weather.entity

其實(shí)覺(jué)得Gson挺好用的……
那我為何不用Gson呢。幔睬。眯漩。因?yàn)槟菚r(shí)候還不會(huì)用@Serializedname,易源數(shù)據(jù)的json竟然還有用數(shù)字開(kāi)頭的key ┭┮﹏┭┮

然后經(jīng)過(guò)了一番的倒騰麻顶,終于一個(gè)個(gè)把數(shù)據(jù)給對(duì)上了= =赦抖,當(dāng)做自己解析json數(shù)據(jù)的練手吧

網(wǎng)絡(luò)請(qǐng)求

主要是用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);
    }
    

直接傳入地址就請(qǐng)求到數(shù)據(jù)了辅肾,

不過(guò)這邊有個(gè)坑6佑!
有個(gè)坑M鹈椤8『獭交胚!

有個(gè)坑7莺埂!蝴簇!

重要的事情所三遍

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

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

數(shù)據(jù)庫(kù)

本人數(shù)據(jù)庫(kù)超級(jí)爛熬词,不過(guò)不算渣渣旁钧,還是能寫點(diǎn)東西,數(shù)據(jù)庫(kù)我設(shè)計(jì)的十分簡(jiǎn)單互拾,只有兩個(gè)重要的屬性歪今,就是城市名和json數(shù)據(jù),為的是在無(wú)網(wǎng)絡(luò)狀態(tài)下從數(shù)據(jù)庫(kù)直接獲取到j(luò)son數(shù)據(jù)颜矿,解析后顯示到界面上寄猩。
框架的話本來(lái)打算用GreenDao的,不過(guò)后面改成LitePal了骑疆。

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

廣告田篇,推送

廣告用的是有米廣告替废,直接對(duì)著SDK把代碼加進(jìn)去就好了,想用騰訊的廣告泊柬,但是打電話給我問(wèn)我有沒(méi)營(yíng)業(yè)執(zhí)照椎镣。。兽赁。状答。暈,沒(méi)有所以沒(méi)有審核通過(guò)闸氮。

推送使用的是極光推送剪况,也是直接使用SDK,本來(lái)使用的是BOMB的,但是Bomb SDK中的okhttp和我自己的依賴起沖突了蒲跨,而且還有一些機(jī)子無(wú)法推送成功译断,所以最后改成了極光推送,這都是血淋淋的坑啊或悲,一步步踩過(guò)來(lái)簡(jiǎn)直吐血孙咪。

    //廣告條初始化
        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);

嵌入廣告就是這么簡(jiǎn)單暴力,但是建議用積分墻巡语,我這個(gè)是廣告條翎蹈。。男公。荤堪。。

因?yàn)槭嗯狻3窝簟!?br> 他們廣告條好像沒(méi)啥廣告踏拜。碎赢。∷俟#可能在實(shí)際中顯示不出來(lái)肮塞,不過(guò)在初始化時(shí)使用測(cè)試廣告的話那就可以看到了。

城市選擇

這里推薦別人寫的一個(gè)依賴姻锁,直接傳送門 CityPicker

用的是高德地圖定位


image
image

桌面小工具

這方面我需要學(xué)習(xí)的東西還有很多的枕赵,開(kāi)啟服務(wù)在后臺(tái)更新,想想后期如果能加入Rxjava位隶,看看能不能優(yōu)化一些操作拷窜,不過(guò)在使用Glide加載圖片到AppWidget時(shí)需要獲取到ImageView控件,所以有折騰了一下。


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

藍(lán)牙和單片機(jī)通信模塊

因?yàn)楸救藢W(xué)過(guò)嵌入式開(kāi)發(fā)装黑,在機(jī)緣巧合的時(shí)候接觸了Android副瀑,所以現(xiàn)在做Android開(kāi)發(fā),單片機(jī)上使用的是DS18B20溫度傳感器恋谭,藍(lán)牙是HC-05,通過(guò)串口進(jìn)行溫度傳輸糠睡,不要覺(jué)得很難,其實(shí)很簡(jiǎn)單疚颊,嗯狈孔,說(shuō)笑的,基礎(chǔ)好就很簡(jiǎn)單啦材义,代碼并不多均抽,曾經(jīng)試過(guò)一次返回?cái)?shù)據(jù)一直都是亂碼,找了一個(gè)星期的問(wèn)題都沒(méi)找到其掂,最后發(fā)現(xiàn)是波特率的問(wèn)題油挥,太感動(dòng)了,傳送門

界面

進(jìn)入APP加載界面款熬,淡入淡出效果深寥,弱引用持有Activity對(duì)象,文字動(dòng)畫效果


緩沖界面
緩沖界面
  //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

這邊其實(shí)沒(méi)有按照Material design的要求透明化狀態(tài)欄贤牛,主界面填充整個(gè)手機(jī)屏幕惋鹅,通過(guò)計(jì)算手機(jī)屏幕總高度,減去狀態(tài)欄的高度和ActionBar的高度殉簸,得出了主界面視圖的高度闰集,就做到了在任何分辨率下都只顯示這樣的界面的效果(原諒我這種拗口的表達(dá),你懂就好哈哈哈哈~~)

  /**
     * 獲取手機(jī)屏幕高度
     *
     * @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;
    }

    /**
     * 獲取手機(jī)屏幕寬度
     *
     * @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;
    }

    /**
     * 反射方法獲取狀態(tài)欄高度
     *
     * @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高度=屏幕高度-標(biāo)題欄高度-狀態(tài)欄高度
        mNowWeatherHeight = SystemUtils.getDisplayHeight(mContext) - SystemUtils.getActionBarSize(mContext) - SystemUtils.getStatusBarHeight(mContext);

每半小時(shí)更新的數(shù)據(jù)list和未來(lái)天氣預(yù)報(bào)

這邊是RecyclerView,在繪制每個(gè)Item的時(shí)候也是計(jì)算了屏幕的寬度般卑,每個(gè)item占屏幕的1/5武鲁,所以在所有分辨率下都只呈現(xiàn)五個(gè)Item

image
image

空氣指數(shù)和生活指數(shù)

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

image
image

城市編輯界面

背景Activity半透明椭微,填充屏幕洞坑,listview側(cè)滑刪除

進(jìn)入Activity后從數(shù)據(jù)庫(kù)中獲取到數(shù)據(jù)盲链,然后顯示到listview中蝇率,進(jìn)行操作后再主界面的onActivityResult中重新獲取數(shù)據(jù)庫(kù)中的內(nèi)容,更新UI.

image
image
//側(cè)滑刪除
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 : 會(huì)關(guān)閉菜單; true :不會(huì)關(guān)閉菜單
                return false;
            }
        });

新聞,笑話侧漓,美圖

這個(gè)模塊寫的說(shuō)實(shí)話我自己都看不下去了锅尘,那時(shí)候?yàn)榱粟s進(jìn)度,,哎藤违,意思一下浪腐。用的是sharepreference進(jìn)行很簡(jiǎn)單的存儲(chǔ)。嗯顿乒,就是這樣的

總結(jié)

僅供參考议街,不得用于商業(yè)項(xiàng)目,如果覺(jué)得對(duì)你有幫助璧榄,給個(gè)Star吧親~
在寫項(xiàng)目的時(shí)候?qū)懥撕枚嗉?xì)節(jié)特漩,都忘了很多了,還是很用心去處理一些問(wèn)題的~
還有引導(dǎo)頁(yè)設(shè)計(jì)的不是很好骨杂,是直接扣網(wǎng)絡(luò)上的圖片涂身,到第三個(gè)界面的時(shí)候點(diǎn)擊一下就可以進(jìn)去了~
謝謝觀看

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市搓蚪,隨后出現(xiàn)的幾起案子蛤售,更是在濱河造成了極大的恐慌,老刑警劉巖妒潭,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悍抑,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡杜耙,警方通過(guò)查閱死者的電腦和手機(jī)搜骡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)佑女,“玉大人记靡,你說(shuō)我怎么就攤上這事⊥徘” “怎么了摸吠?”我有些...
    開(kāi)封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)嚎花。 經(jīng)常有香客問(wèn)我寸痢,道長(zhǎng),這世上最難降的妖魔是什么紊选? 我笑而不...
    開(kāi)封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任啼止,我火速辦了婚禮,結(jié)果婚禮上兵罢,老公的妹妹穿的比我還像新娘献烦。我一直安慰自己,他們只是感情好卖词,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布巩那。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪即横。 梳的紋絲不亂的頭發(fā)上噪生,一...
    開(kāi)封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音东囚,去河邊找鬼杠园。 笑死,一個(gè)胖子當(dāng)著我的面吹牛舔庶,可吹牛的內(nèi)容都是我干的抛蚁。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼惕橙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼瞧甩!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起弥鹦,我...
    開(kāi)封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤肚逸,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后彬坏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體朦促,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年栓始,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了务冕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡幻赚,死狀恐怖禀忆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情落恼,我是刑警寧澤箩退,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站佳谦,受9級(jí)特大地震影響戴涝,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜钻蔑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一啥刻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧矢棚,春花似錦郑什、人聲如沸府喳。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至兜粘,卻和暖如春申窘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背孔轴。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工剃法, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人路鹰。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓贷洲,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親晋柱。 傳聞我的和親對(duì)象是個(gè)殘疾皇子优构,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容