Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 安卓盒子launcher界面開發之添加自動定位,獲取當地天氣

安卓盒子launcher界面開發之添加自動定位,獲取當地天氣

編輯:關於Android編程

最近老板要求在launcher界面做個自動定位,並獲取當地天氣的功能,中間走了不少彎路,我在這裡都寫下來,希望看到這篇文章的人,能少走點彎路。 \ 1、接到任務後,我首先想的是,先把天氣獲取到(比如獲取深圳本地的),然後再做定位的功能 有了大致的思路後,就著手開始做了,因為公司是做國外的生意,所以用的是雅虎的api,說起來雅虎,年前自己搞個天氣玩了下,用的就是雅虎的,是解析woeid的,當時是可以用的,不清楚從什麼時候用不了 就變成了如下這樣 \   然後就到雅虎的官網上找別的方法https://developer.yahoo.com/weather/,因為之前參考網上的例子,原作者是用sax解析xml,我也就依葫蘆畫瓢想用sax解析,xml是這樣的 \   ok,但是後來發現,遇到了困難,用的方法不對。想了下,還是用json的解析,比較熟悉些。然後訪問雅虎返回的json數據是這樣的 \ 是不是看著頭都大了,本菜菜當時一看頓時嚇尿,這裡推薦一個在線轉換json格式(http://json.cn/) 效果圖是這樣的
\ 是不是感覺清晰了很多? 這裡返回的數據,需要層層遞取的,下面貼代碼, 這裡我用了voelly框架,封裝好的方法,用起來就是爽,話說還沒用過的請自行百度,真的很好用(哈哈,這裡感謝基友浩的鼎力幫助) privateRequestQueuemQueue; mQueue=Volley.newRequestQueue(this); 需要導包的 privatevoidgetData(Stringurl){//解析的方法 JsonObjectRequestjsonObjectRequest=newJsonObjectRequest(url,null,newListener(){ @Override publicvoidonResponse(JSONObjectresponse){   try{ //JSONObject 解析”query“數組 JSONObjectqueryJSONObject=(JSONObject)response.getJSONObject("query"); JSONObjectchannelJSONObject= queryJSONObject.getJSONObject("results").getJSONObject("channel");//逐層取..... //下面就是要獲得的東西咯 JSONObjectlocationJSONObject=channelJSONObject.getJSONObject("location"); //國家、省份、城市 tx_city.setText(locationJSONObject.getString("city")+""+locationJSONObject.getString("region") +""+locationJSONObject.getString("country"));   JSONObjectitemJSONObject=channelJSONObject.getJSONObject("item"); //天氣情況 JSONArrayforecastJSONArray=itemJSONObject.getJSONArray("forecast");   StringdescriptionString=itemJSONObject.getString("description");   StringBuilderdescriptionSB=newStringBuilder(descriptionString); //獲取雅虎的天氣圖像(蠻丑的,(⊙o⊙)…) StringimgUrl=descriptionSB.substring( descriptionString.indexOf(" descriptionString.lastIndexOf("\"/>")); //Log.d(TAG,"imgUrl++++is"+imgUrl);   for(inti=0;i //這裡我只要當天的天氣,取的是“0” JSONObjectdayWeatherJSONObject=forecastJSONArray.getJSONObject(0); ((TextView)findViewById(R.id.tx_condition)).setText(dayWeatherJSONObject.getString("text"));   //得到的是華攝氏度轉化為攝氏度 tx_temp.setText(""+(int)(((Integer.parseInt(dayWeatherJSONObject.getString("low")))-32)/1.8)+ "/"+(int)(((Integer.parseInt(dayWeatherJSONObject.getString("high")))-32)/1.8)+ getResources().getString(R.string.str_temp)); //這裡取字符串加了個判斷 if(imgUrl.length()==37){ Stringpic=imgUrl.substring(31,37); img_weather.setImageResource(parseIcon2(pic));//替換雅虎圖片的方法 }elseif(imgUrl.length()==36){ Stringpic=imgUrl.substring(31,36); img_weather.setImageResource(parseIcon2(pic)); }   }   }catch(JSONExceptione){ e.printStackTrace(); }   } },newErrorListener(){   @Override publicvoidonErrorResponse(VolleyErrorarg0){   } });   mQueue.add(jsonObjectRequest); }   privateintparseIcon2(StringstrIcon){ if(strIcon==null) return-1; if("31.gif".equals(strIcon)||"32.gif".equals(strIcon)|| "33.gif".equals(strIcon)||"34.gif".equals(strIcon)||"36.gif".equals(strIcon)) returnR.drawable.sunny03; if("23.gif".equals(strIcon)||"24.gif".equals(strIcon)||"26.gif".equals(strIcon)||"27.gif".equals(strIcon)||"28.gif".equals(strIcon) ||"30.gif".equals(strIcon)||"44.gif".equals(strIcon)) returnR.drawable.cloudy03; if("29.gif".equals(strIcon)) returnR.drawable.shade03; if("40.gif".equals(strIcon)) returnR.drawable.shower01; if("4.gif".equals(strIcon)) returnR.drawable.thunder_shower03; if("13.gif".equals(strIcon)) returnR.drawable.snow_shower03; if("25.gif".equals(strIcon)) returnR.drawable.s_snow03; if("14.gif".equals(strIcon)||"15.gif".equals(strIcon)) returnR.drawable.m_snow03; if("16.gif".equals(strIcon)||"42.gif".equals(strIcon)) returnR.drawable.l_snow03; if("43.gif".equals(strIcon)||"41.gif".equals(strIcon)) returnR.drawable.h_snow03; if("20.gif".equals(strIcon)||"21.gif".equals(strIcon)||"22.gif".equals(strIcon)) returnR.drawable.fog03; if("6.gif".equals(strIcon)) returnR.drawable.ics_rain; if("7.gif".equals(strIcon)||"17.gif".equals(strIcon)||"35.gif".equals(strIcon)) returnR.drawable.rain_and_hail; if("5.gif".equals(strIcon)||"18.gif".equals(strIcon)) returnR.drawable.rain_and_snow; //-- if("8.gif".equals(strIcon)||"9.gif".equals(strIcon)) returnR.drawable.s_rain03; //-- if("10.gif".equals(strIcon)) returnR.drawable.m_rain03; if("11.gif".equals(strIcon)||"12.gif".equals(strIcon)) returnR.drawable.l_rain03; if("45.gif".equals(strIcon)||"47.gif".equals(strIcon)||"39.gif".equals(strIcon)) returnR.drawable.h_rain03; if("38.gif".equals(strIcon)) returnR.drawable.hh_rain03; if("3.gif".equals(strIcon)||"37.gif".equals(strIcon)) returnR.drawable.hhh_rain03; if("29.gif".equals(strIcon)) returnR.drawable.smoke03; if("2.gif".equals(strIcon)||"19.gif".equals(strIcon)) returnR.drawable.sand_blowing03; if("1.gif".equals(strIcon)) returnR.drawable.sand_storm02; if("0.gif".equals(strIcon)) returnR.drawable.sand_storm03; returnR.drawable.sunny03;   }     上面的這些,已經可以解析出深圳當地的天氣啦,在盒子裡運行,果斷可以顯示了,當時是在launcher代碼裡,用動態廣播做了監聽,如果有網絡,就顯示在主頁上。 2、下面就是實現定位的功能了(話說也折騰了我很久,且聽我詳細道來,以後大家開發東西的時候一定要想好,用哪些方法,調用什麼,一定要想好,最好寫下來,再去實施) 上面說了,公司做的是國外的生意,所以,高德pass了,我們的盒子上沒gps,pass,wifi定位的是我後來才想到了,這裡,說下,網上資料的一個坑,大家如果用到了這個方法,還是立馬停止的好 \ 這裡訪問google,一是需要翻牆,這個對我們公司倒是沒有壓力。把現成的方法copy進去,就發現了問題 \ 這裡一直得到的是null值,跟了代碼,不是很明白,一直走不到下一步,在網上查了下,說是這個google的服務器停了(欲哭無淚),有點懷疑,因為打印,取到的是亂碼,我也無從考察,因為時間很緊,果斷換了方法了。 然後說下能全球定位的其他兩個方法,google和百度,如果單從我們公司出發,肯定google定位是首先,為此我還申請了key。但goolge定位的,需要些services,還有些其他的原因,搞了一天沒搞出來,果斷換了。 去看了百度這地圖的官方文檔,上面也有現成的demo可以參考,下載下來過後,運行,定位ok。把需要的code放到源碼環境下編譯,需要倒入jar包和.so文件。Android.mk配置
\ mm 該工程,編譯通過,out目錄該工程目錄下成功生成了lib文件.so自然在其中了,需要手動把你的.so放到system/lib下,在盒子上測試,你需要把.so放到system/lib下,修改權限,把out目錄下生成該工程的apk,push到盒子裡,替換,當聯網的時候,盒子一直閃屏,查看logcat打印的報錯信息,如下: \
\ 不可用?!因為之前參考的demo不是最新的.so和jar包,更換了百度最新的.so和jar包,重復上面的過程,還是報同樣的錯誤,在網上搜了一下,說是可能不兼容的處理器,問了下硬件,我們是64位的處理器,但是軟件是32的,什麼鬼?ok,用笨方法,一個試總可以吧 \ 試完以上的所有.so還是閃屏不斷,崩潰了快,這樣編譯百度.so,jar到系統中,反復測試,耽誤了不少時間。一時陷入僵局(這個問題是兼容的問題,還是so文件配置出了問題,到現在也沒頭緒,如果有大神讀到小弟的這篇文章,還請不吝賜教,感謝感謝)。和基友浩交流,決定用強大的SP(SharedPreference)把獲得的定位城市數據傳遞到 launcher APK,可以將apk的數據傳遞到apk2 \
\ 打印,得到的"lucy",可是後來遇到個問題,需要傳遞的是city=res.addressComponents.city;百度定位獲得的city,卻傳不過去了。想了下,用廣播的方式傳值,有個方法 Intenti=newIntent(); i.setAction("com.example.perference.shared_id"); i.putExtra("city",city); sendBroadcast(i); 3、城市定位apk與launcher APK的數據傳送 連上wifi發送此廣播 if((action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION))||action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)|| action.equals(ConnectivityManager.CONNECTIVITY_ACTION)){ Intentsend=newIntent(); send.setAction("com.weather.broadcast"); send.putExtra("launcher","weather"); Launcher.this.sendBroadcast(send); Log.d(TAG,"sendBroadcastReceiver++++++++="); } 定位apk監聽此廣播 publicclassMyBroadcastextendsBroadcastReceiver{ privatestaticfinalStringTAG="MyBroadcast"; publicfinalStringweather_broadcat="com.weather.broadcast";//接收到此廣播 @Override publicvoidonReceive(Contextcontent,Intentintent) {   if(intent.getAction().equals(weather_broadcat)){ Stringstr=intent.getExtras().getString("launcher"); //Log.d(TAG,"+++++"+str); intent=newIntent(content,MyService.class); content.startService(intent); //啟動後台service服務 //Log.d(TAG,"intent++++++++over"); }   }   } 啟動service,開啟定位,獲取當地城市 publicclassMyServiceextendsService{   privatestaticfinalStringTAG="MyService"; privateBMapManagermBMapMan=null; privateLocationListenermLocationListener=null; privateMKSearchmSearch=null; privatefinalStringweather_receive_action="com.example.perference.shared_id"; staticStringcity; privateHandlerhandler=newHandler(); @Override publicIBinderonBind(Intentintent)/*noted*/ {   returnnull; } @Override publicvoidonCreate(){ //Log.d(TAG,"onCreate()+++++++"); initBaiDuMap(); mBMapMan.getLocationManager().requestLocationUpdates(mLocationListener); mBMapMan.getLocationManager().enableProvider(MKLocationManager.MK_GPS_PROVIDER); mBMapMan.start(); } @Override publicintonStartCommand(Intentintent,intflags,intstartId){ //Log.d(TAG,"onStartCommand++++++++"); initBaiDuMap(); mBMapMan.getLocationManager().requestLocationUpdates(mLocationListener); mBMapMan.getLocationManager().enableProvider(MKLocationManager.MK_GPS_PROVIDER); mBMapMan.start(); returnsuper.onStartCommand(intent,flags,startId); }   publicvoidinitBaiDuMap(){ mBMapMan=newBMapManager(getApplication()); mBMapMan.init("14A97FC2DDF678193F61C19C0A20EA29C49DEF5C",null); mBMapMan.start(); initMyLocation(); //Log.d(TAG,"initMyLocation()+++++++"); } privatevoidinitMyLocation(){ mLocationListener=newLocationListener(){ @Override publicvoidonLocationChanged(Locationlocation){ if(location!=null){ GeoPointmyPt=newGeoPoint((int)(location.getLatitude()*1e6), (int)(location.getLongitude()*1e6)); initMapSerach(); mSearch.reverseGeocode(myPt); }else{ } } }; } privatevoidinitMapSerach(){ //Log.d(TAG,"thefirst1+++++"); mSearch=newMKSearch(); mSearch.init(mBMapMan,newMKSearchListener(){   publicvoidonGetPoiResult(MKPoiResultres,inttype,interror){   } publicvoidonGetDrivingRouteResult(MKDrivingRouteResultres, interror){ } publicvoidonGetTransitRouteResult(MKTransitRouteResultres, interror){ } publicvoidonGetWalkingRouteResult(MKWalkingRouteResultres, interror){ } publicvoidonGetAddrResult(MKAddrInfores,interror){ if(error!=0||res==null){ //Log.d(TAG,"isnoterror"); }else{ //獲取到城市和省份 city=res.addressComponents.city; Stringpro=res.addressComponents.province; newThread(){ publicvoidrun(){ Intenti=newIntent(); i.setAction("com.example.perference.shared_id"); i.putExtra("city",city); //Log.d(TAG,"city====="+city); sendBroadcast(i); handler.postDelayed(this,600000); //隔十分鐘更新一次 } }.start();   } } @Override publicvoidonGetBusDetailResult(MKBusLineResultarg0,intarg1){   } });   } } launcher APK 接收到廣播,調用解析方法,JSONObject解析,在主界面更新顯示 privateBroadcastReceivernetReceiver=newBroadcastReceiver(){ @Override publicvoidonReceive(Contextcontext,Intentintent){ Stringaction=intent.getAction();   if(action==null) return;   Log.d(TAG,"netReceiveraction="+action);   if(action.equals(outputmode_change_action)){ setHeight(); }   if(action.equals(Intent.ACTION_TIME_TICK)){ displayDate();   time_count++; if(time_count>=time_freq){ sendWeatherBroadcast(); time_count=0; } }if((action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION))||action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)|| action.equals(ConnectivityManager.CONNECTIVITY_ACTION)){ Intentsend=newIntent(); send.setAction("com.weather.broadcast"); send.putExtra("launcher","weather"); Launcher.this.sendBroadcast(send); Log.d(TAG,"sendBroadcastReceiver++++++++="); } if(action.equals(net_change_action)){   } elseif(action.equals(weather_receive_action)){ //接收service發送的廣播,然後調用方法解析 StringweatherInfo=intent.getExtras().getString("weather_today"); setWeatherView(weatherInfo); StringweatherCity=intent.getExtras().getString("city"); //得到定位到的城市 urlcity="https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D'"+weatherCity+"')&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys"; //雅虎json查詢天氣語句 getData(urlcity); //調用解析方法 }elseif(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action) ||Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)){ updateAppList(intent); }else{ updateWifiLevel(); displayStatus(); updateStatus(); } } }; 最後說一下,因為定位只在移動網絡上有效,query 這個button按鈕是為了客戶連接以太網,手動輸入城市,獲取天氣兒准備的 query_button.setOnClickListener(newOnClickListener(){ @Override publicvoidonClick(Viewv){ /**因為開機EditText會自動獲取焦點,從而調系統的軟鍵盤,所以在xml設置成了android:visibility="gone" 這裡,點擊EditText才會顯示軟鍵盤*/ etCity.setVisibility(View.VISIBLE); finalStringmCityStr=etCity.getText().toString(); StringCityCodeUrl=""; if(!mCityStr.isEmpty()){ tx_city.setVisibility(View.GONE); CityCodeUrl="https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D'"+mCityStr+"')&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys"; getData(CityCodeUrl); //Log.d(TAG,"queryonclick+++"); }else{ Toast.makeText(Launcher.this,"Pleaseenteracityname",Toast.LENGTH_SHORT).show(); } } }); } 希望可以幫到大家,如有有錯誤,請幫忙指正。謝謝!

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved