安卓盒子launcher界面开发之添加自动定位,获取当地天气

Posted yun382657988

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了安卓盒子launcher界面开发之添加自动定位,获取当地天气相关的知识,希望对你有一定的参考价值。

  最近老板要求在launcher界面做个自动定位,并获取当地天气的功能,中间走了不少弯路,我在这里都写下来,希望看到这篇文章的人,能少走点弯路。(先上图,嘿嘿)

 

   1、接到任务后,我首先想的是,先把天气获取到(比如获取深圳本地的),然后再做定位的功能

    有了大致的思路后,就着手开始做了,因为公司是做国外的生意,所以用的是雅虎的api,说起来雅虎,年前自己搞个天气玩了下,用的就是雅虎的,是解析woeid的,当时是可以用的,不清楚从什么时候用不了

就变成了如下这样

 

然后就到雅虎的官网上找别的方法https://developer.yahoo.com/weather/,因为之前参考网上的例子,原作者是用sax解析xml,我也就依葫芦画瓢想用sax解析,xml是这样的

 

ok,但是后来发现,遇到了困难,用的方法不对。想了下,还是用json的解析,比较熟悉些。然后访问雅虎返回的json数据是这样的

是不是看着头都大了,本菜菜当时一看顿时吓尿,这里推荐一个在线转换json格式(http://json.cn/

效果图是这样的

是不是感觉清晰了很多?

 这里返回的数据,需要层层递取的,下面贴代码,

这里我用了voelly框架,封装好的方法,用起来就是爽,话说还没用过的请自行百度,真的很好用(哈哈,这里感谢基友浩的鼎力帮助)

private RequestQueue mQueue;

mQueue = Volley.newRequestQueue(this);

需要导包的

private void getData(String url) {//解析的方法

        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(url, null, new Listener<JSONObject>() {

            @Override

            public void onResponse(JSONObject response) {

 

                try {

                     // JSONObject 解析”query“数组

                    JSONObject queryJSONObject = (JSONObject) response.getJSONObject("query");

                    JSONObject channelJSONObject =                           queryJSONObject.getJSONObject("results").getJSONObject("channel");//逐层取.....

                     //下面就是要获得的东西咯

                    JSONObject locationJSONObject = channelJSONObject.getJSONObject("location");

                   //国家、省份、城市

                    tx_city.setText(locationJSONObject.getString("city")+" "+locationJSONObject.getString("region")

                          + " "+ locationJSONObject.getString("country"));

 

                    JSONObject itemJSONObject = channelJSONObject.getJSONObject("item");

                     //天气情况

                    JSONArray forecastJSONArray = itemJSONObject.getJSONArray("forecast");

 

                    String descriptionString = itemJSONObject.getString("description");

 

                    StringBuilder descriptionSB = new StringBuilder(descriptionString);

                    //获取雅虎的天气图像(蛮丑的,(⊙o⊙)…)

                    String imgUrl = descriptionSB.substring(

                            descriptionString.indexOf("<img src=\\"") + "<img src=\\"".length(),

                            descriptionString.lastIndexOf("\\"/>"));

                            //Log.d(TAG,"imgUrl++++is"+imgUrl);

 

                    for (int i = 0; i < forecastJSONArray.length(); i++) {

                        //这里我只要当天的天气,取的是“0”

                        JSONObject dayWeatherJSONObject = 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){

                            String pic=imgUrl.substring(31, 37);

                            img_weather.setImageResource(parseIcon2(pic));//替换雅虎图片的方法

                        }else if(imgUrl.length()==36){

                            String pic=imgUrl.substring(31, 36);

                            img_weather.setImageResource(parseIcon2(pic));

                        }

 

                    }

 

                } catch (JSONException e) {

                    e.printStackTrace();

                }

 

            }

        }, new ErrorListener() {

 

            @Override

            public void onErrorResponse(VolleyError arg0) {

 

            }

        });

 

        mQueue.add(jsonObjectRequest);

    }

 

    private int parseIcon2(String strIcon) {

        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))

            return R.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))

            return R.drawable.cloudy03;

        if ("29.gif".equals(strIcon))

            return R.drawable.shade03;

        if ("40.gif".equals(strIcon))

            return R.drawable.shower01;

        if ("4.gif".equals(strIcon))

            return R.drawable.thunder_shower03;

        if ("13.gif".equals(strIcon))

            return R.drawable.snow_shower03;

        if ("25.gif".equals(strIcon))

            return R.drawable.s_snow03;

        if ("14.gif".equals(strIcon)||"15.gif".equals(strIcon))

            return R.drawable.m_snow03;

        if ("16.gif".equals(strIcon)||"42.gif".equals(strIcon))

            return R.drawable.l_snow03;

        if ("43.gif".equals(strIcon)||"41.gif".equals(strIcon))

            return R.drawable.h_snow03;

        if ("20.gif".equals(strIcon)||"21.gif".equals(strIcon)||"22.gif".equals(strIcon))

            return R.drawable.fog03;

        if ("6.gif".equals(strIcon))

            return R.drawable.ics_rain;

        if ("7.gif".equals(strIcon)||"17.gif".equals(strIcon)||"35.gif".equals(strIcon))

            return R.drawable.rain_and_hail;

        if ("5.gif".equals(strIcon)||"18.gif".equals(strIcon))

            return R.drawable.rain_and_snow;

          //--

        if ("8.gif".equals(strIcon)||"9.gif".equals(strIcon))

            return R.drawable.s_rain03;

        //--

        if ("10.gif".equals(strIcon))

            return R.drawable.m_rain03;

        if ("11.gif".equals(strIcon)||"12.gif".equals(strIcon))

            return R.drawable.l_rain03;

        if ("45.gif".equals(strIcon)||"47.gif".equals(strIcon)||"39.gif".equals(strIcon))

            return R.drawable.h_rain03;

        if ("38.gif".equals(strIcon))

            return R.drawable.hh_rain03;

        if ("3.gif".equals(strIcon)||"37.gif".equals(strIcon))

            return R.drawable.hhh_rain03;

        if ("29.gif".equals(strIcon))

            return R.drawable.smoke03;

        if ("2.gif".equals(strIcon)||"19.gif".equals(strIcon))

            return R.drawable.sand_blowing03;

        if ("1.gif".equals(strIcon))

            return R.drawable.sand_storm02;

        if ("0.gif".equals(strIcon))

            return R.drawable.sand_storm03;

        return R.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,却传不过去了。想了下,用广播的方式传值,有个方法

Intent i = new Intent();

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)){

                Intent send = new Intent();

                send.setAction("com.weather.broadcast");

                send.putExtra("launcher", "weather");

                Launcher.this.sendBroadcast(send);

                Log.d(TAG,"send BroadcastReceiver++++++++=");

            }

定位apk监听此广播

public class MyBroadcast extends BroadcastReceiver{

    private static final String TAG = "MyBroadcast";

    public final String weather_broadcat = "com.weather.broadcast";//接收到此广播

    @Override

    public void onReceive(Context content, Intent intent)

    {

 

        if(intent.getAction().equals(weather_broadcat)){

            String str = intent.getExtras().getString("launcher");

            //Log.d(TAG, "+++++"+str);

            intent =new Intent(content,MyService.class);

            content.startService(intent);                                  //启动后台service服务

            //Log.d(TAG, "intent++++++++over");

        }

 

    }

 

}

启动service,开启定位,获取当地城市

public class MyService extends Service{

 

    private static final String TAG = "MyService";

    private BMapManager mBMapMan = null;

    private LocationListener mLocationListener = null;

    private MKSearch mSearch = null;

    private final String weather_receive_action = "com.example.perference.shared_id";

    static String city;

    private Handler handler = new Handler();

    @Override

    public IBinder onBind(Intent intent)/*noted*/

    {

 

        return null;

    }

    @Override

    public void onCreate() {

        //Log.d(TAG, "onCreate()+++++++");

        initBaiDuMap();

        mBMapMan.getLocationManager().requestLocationUpdates(mLocationListener);

        mBMapMan.getLocationManager().enableProvider(MKLocationManager.MK_GPS_PROVIDER);

        mBMapMan.start();

    }

    @Override

    public int onStartCommand(Intent intent, int flags, int startId) {

        //Log.d(TAG, "onStartCommand++++++++");

        initBaiDuMap();

        mBMapMan.getLocationManager().requestLocationUpdates(mLocationListener);

        mBMapMan.getLocationManager().enableProvider(MKLocationManager.MK_GPS_PROVIDER);

        mBMapMan.start();

        return super.onStartCommand(intent, flags, startId);    

    }

 

    public  void initBaiDuMap(){

        mBMapMan = new BMapManager(getApplication());

        mBMapMan.init("14A97FC2DDF678193F61C19C0A20EA29C49DEF5C", null);

        mBMapMan.start();

        initMyLocation();

        //Log.d(TAG, "initMyLocation()+++++++");

    }

    private void initMyLocation(){

        mLocationListener = new LocationListener(){

            @Override

            public void onLocationChanged(Location location) {

                if(location != null){

                    GeoPoint myPt = new GeoPoint((int)(location.getLatitude()*1e6),

                            (int)(location.getLongitude()*1e6));

                    initMapSerach();

                    mSearch.reverseGeocode(myPt);

                }else{

                }

            }

        };

    }

    private void initMapSerach(){

        //Log.d(TAG, "the first1+++++");

        mSearch = new MKSearch();

        mSearch.init(mBMapMan, new MKSearchListener(){

 

                public void onGetPoiResult(MKPoiResult res, int type, int error) {

 

                }

                public void onGetDrivingRouteResult(MKDrivingRouteResult res,

                        int error) {

                }

                public void onGetTransitRouteResult(MKTransitRouteResult res,

                        int error) {

                }

                public void onGetWalkingRouteResult(MKWalkingRouteResult res,

                        int error) {

                }

                public void onGetAddrResult(MKAddrInfo res, int error) {

                    if (error != 0 || res == null) {

                        //Log.d(TAG, "is not error");

                    }else{

                        //获取到城市和省份

                        city = res.addressComponents.city;

                        String pro = res.addressComponents.province;

                        new Thread(){

                            public void run(){

                                Intent i = new Intent();

                                i.setAction("com.example.perference.shared_id");

                                i.putExtra("city",city); 

                                //Log.d(TAG, "city====="+city);

                                sendBroadcast(i);

                                handler.postDelayed(this, 600000);    //隔十分钟更新一次

                            }

                        }.start();

 

                    }

                }

                @Override

                public void onGetBusDetailResult(MKBusLineResult arg0, int arg1) {

 

                }

        });

 

        }

}

launcher APK 接收到广播,调用解析方法,JSONObject解析,在主界面更新显示

private BroadcastReceiver netReceiver = new BroadcastReceiver() {

        @Override

        public void onReceive(Context context, Intent intent) {

            String action = intent.getAction();

 

            if(action == null)

                return;

 

            Log.d(TAG, "netReceiver         action = " + 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)){

                Intent send = new Intent();

                send.setAction("com.weather.broadcast");

                send.putExtra("launcher", "weather");

                Launcher.this.sendBroadcast(send);

                Log.d(TAG,"send BroadcastReceiver++++++++=");

            }

            if(action.equals(net_change_action)){

 

            } 

            else if (action.equals(weather_receive_action)) {   //接收service发送的广播,然后调用方法解析

                String weatherInfo = intent.getExtras().getString("weather_today");

                setWeatherView(weatherInfo);

                String weatherCity = 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);                                                                 //调用解析方法

            } else if(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(new OnClickListener(){

            @Override

            public void onClick(View v){

                /**因为开机EditText会自动获取焦点,从而调系统的软键盘,所以在xml设置成了 android:visibility="gone"

                  这里,点击EditText才会显示软键盘*/

                etCity.setVisibility(View.VISIBLE); 

                final String mCityStr = etCity.getText().toString();

                String CityCodeUrl = "";

                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, "query on click+++");

                }else{

                    Toast.makeText(Launcher.this,"Please enter a city name" , Toast.LENGTH_SHORT).show();

                }

            }

        });

    }

希望可以帮到大家,如有错误,请帮忙指正。谢谢!
发下我定位天气apk的百度云链接
http://pan.baidu.com/s/1o8vk2Bg

以上是关于安卓盒子launcher界面开发之添加自动定位,获取当地天气的主要内容,如果未能解决你的问题,请参考以下文章

安卓Launcher之获取手机安装的应用列表,安卓launcher

python 之 前端开发(盒子模型页面布局浮动定位z-indexoverflow溢出)

系统方向学习总结6 --Launcher3拖拽分析之Workspace

系统方向学习总结6 --Launcher3拖拽分析之Workspace

系统方向学习总结6 --Launcher3拖拽分析之Workspace

系统方向学习总结6 --Launcher3拖拽分析之Workspace