和风SDK查询城市ID(保姆级教程)

news2024/11/14 23:30:45

android studio版本:2021.2.1

例程名:hfserachcityid

这几天没什么事做,而且我原来那个“项目”因为免费api不能用了,只能改为和风的免费api,但需要申请,而且还要城市ID,玩天气的基本都知道城市ID这个东西,之前我找到一个在网页上查询城市 ID的网址,但现在也用不了了,我记得好像还哪里可以查,但不记得了。既然和风也可以查,就再做个app不就行了,其实也可以把代码 放到我那个“项目”里,这事以后再说。而且还可以顺便学点东西,我肯定会遇到问题的,解决的过程就是学习的过程。可没想到这个东西还真给我找了不少麻烦,也算学到了东西。我之前做过一个“andriod 和风天气SDK获取实时天气(保姆级教程)”,我原本想这不是一样吗?代码都不用大的改动,其实不一样,而且我现在怀疑那个教程的代码还能不能用,我真想不通,代码干嘛改动那么大?这样以前做的东西不都用不了?算了,生气也没用。先说说两个为难我的地方。

  1. 这个东西获取的城市数据是List<LocationBean>这种格式(相关数据格式见:https://dev.qweather.com/docs/android-sdk/geoapi/android-city-lookup/),我以为是list,于是按照list<bean>的获取值方法好一顿折腾,就是不成功,原来获取天气的时候就很简单,而且当时还提供例程代码,现在好了,例程代码也没有了,只能一遍遍试, 因为我真不会啊。而且原来获取天气的代码搬过来没好使。折腾我好几天。

  1. 在获取天气的时候,直接可以在代码里面修改ui界面,在这里不行,settext出现致命错误:Only the original thread that created a view hierarchy can touch its views.一查才知道不可以在非ui线程更新ui线程(其实我哪里知道,后来才知道是这么回事。)于是又查解决办法,书到用时方恨少啊。

好了,剩下的就是如何完整的做这个app了。

重要:申请key之前先建立项目,项目的package name要用,不建立没有这个名称。

一、申请免费和风key.

 网址:https://id.qweather.com/#/register?redirect=https%3A%2F%2Fconsole.qweather.com

注册略。

登录后进入“和风天气开发者控制台”

点击左侧"项目管理":

进入后点击右侧"添加key"进入下图(上图只是演示,和风只能申请3个免费KEY):选择“android SDK”,key的名称随便写,package name "必须"与你的appg 一致,否则无法获取数据。(下面有提示如何获取package name,一般类似com.example.nothing这样。)

点击创建后如下图,就得到了key 和public id.这两个在代码里和风初始化的时候都要用到。

至此和风免费key申请完成,此key每天有1000次免费访问,足够了。

二、新建项目。(android studio2021.2.1)

file-new-newproject后如下图:选择empty activity.

next后:

项目名称自选,我写的nothing是为了配合刚才那个和风key.最下面的minimumsdk是指最小兼容版本,看个人需要,这个以后也可以改。点finish完成。

三、项目配置:

城市搜索开发文档:https://dev.qweather.com/docs/android-sdk/geoapi/android-city-lookup/

sdk下载:https://dev.qweather.com/docs/configuration/android-sdk-config/

把下载的sdk文件放到下图的文件夹内:libs必须在project模式下才能看到,可以在系统“文件管理器”打开如下路径:AndroidStudioProjects\nothing\app\libs

在android studio内打开文件夹在sdk文件上右键,点击最下面add as library完成sdk导入

添加权限。打开:androidmanafest.xml文件

添加如下权限:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

权限意义:

权限添加androidmanafest.xml位置如图示:

引用库。打开如下图build gradle文件,添加如下库:

    compile 'com.squareup.okhttp3:okhttp:3.12.12' (3.12.12+)
    compile 'com.google.code.gson:gson:2.6.2'   (2.6.2+)

至此项目配置完成。

四、项目代码。主要部分都有注释。注意本代码不是nothing的代码,注意包名。

activity_main.xml(布局根据个人喜好,下面是我使用的相对布局)

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/title1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="76dp"
        android:text="城市ID查询程序"
        android:textColor="@android:color/holo_red_light"
        android:textSize="20sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/inputcity"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="140dp"
        android:text="请输入查询地区/城市:"
        android:textColor="@color/black"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.167"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/cityname"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="96dp"
        android:text="地区/城市名:"
        android:textColor="@color/black"
        app:layout_constraintStart_toStartOf="@+id/inputcity"
        app:layout_constraintTop_toBottomOf="@+id/inputcity" />

    <TextView
        android:id="@+id/cityid"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="地区/城市ID:"
        android:textColor="@color/black"
        app:layout_constraintStart_toStartOf="@+id/cityname"
        app:layout_constraintTop_toBottomOf="@+id/cityname" />

    <TextView
        android:id="@+id/belonearea"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="所属行政区域:"
        android:textColor="@color/black"
        app:layout_constraintStart_toStartOf="@+id/cityid"
        app:layout_constraintTop_toBottomOf="@+id/cityid" />

    <TextView
        android:id="@+id/textView11"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="上级城市:"
        android:textColor="@color/black"
        app:layout_constraintStart_toStartOf="@+id/belonearea"
        app:layout_constraintTop_toBottomOf="@+id/belonearea" />

    <EditText
        android:id="@+id/input"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="19dp"
        android:ems="8"
        android:inputType="textPersonName"
        android:minHeight="48dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toEndOf="@+id/inputcity"
        app:layout_constraintTop_toBottomOf="@+id/title1"
        tools:ignore="SpeakableTextPresentCheck" />

    <TextView
        android:id="@+id/cityname1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="123"
        app:layout_constraintStart_toEndOf="@+id/cityname"
        app:layout_constraintTop_toTopOf="@+id/cityname" />

    <TextView
        android:id="@+id/cityid1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="28dp"
        android:text="456"
        app:layout_constraintBottom_toBottomOf="@+id/cityid"
        app:layout_constraintStart_toEndOf="@+id/cityname"
        app:layout_constraintTop_toTopOf="@+id/cityname1" />

    <TextView
        android:id="@+id/area1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="456"
        app:layout_constraintBottom_toBottomOf="@+id/belonearea"
        app:layout_constraintStart_toEndOf="@+id/belonearea" />

    <TextView
        android:id="@+id/area"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="456"
        app:layout_constraintBottom_toBottomOf="@+id/textView11"
        app:layout_constraintStart_toEndOf="@+id/belonearea" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="确定"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.486"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/input"
        app:layout_constraintVertical_bias="0.0" />
</androidx.constraintlayout.widget.ConstraintLayout>

mainactivity.java

package com.example.hfserachcityid;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.google.gson.Gson;
import com.qweather.sdk.bean.base.Code;
import com.qweather.sdk.bean.geo.GeoBean;
import com.qweather.sdk.view.HeConfig;
import com.qweather.sdk.view.QWeather;

public class MainActivity extends AppCompatActivity {
    public TextView viewname,viewid,viewarea,viewarea1;
    private EditText inputcity;
    private Button button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        viewname=(TextView)findViewById(R.id.cityname1);
        viewid=(TextView)findViewById(R.id.cityid1);
        viewarea=(TextView)findViewById(R.id.area);
        viewarea1=(TextView)findViewById(R.id.area1);
        inputcity=(EditText)findViewById(R.id.input);
        button=(Button)findViewById(R.id.button);
        //和风初始化
        HeConfig.init("HE2303010152481612", "3cbc9266e3b24f38afbf182611fc3de4");
        HeConfig.switchToDevService();
        //按钮监听
        button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                //此处注意,gettext的值如果为空,不可以用inputcity.gettext().tostring()=="",此值永远非空。
                //只能用equals,如果有值可以用==方式。
                String string="";
                //如果为空值无动作,非空开始查询。
                if(string.equals(inputcity.getText().toString())){
                }else{
                    getCity();
                }
            }
        });
    }
    //获取数据及解析关键代码
    public void getCity(){
        //获取输入框内容
        String inputct =inputcity.getText().toString();
        //此方法为和风提供
        QWeather.getGeoCityLookup(MainActivity.this, inputct,  new QWeather.OnResultGeoListener(){
            public static final String TAG="he_feng_city";
            //如果提供数据有问题显示          
            @Override
            public void onError(Throwable e) {
                Log.i(TAG, "onError: ", e);
                System.out.println("Weather Now Error:"+new Gson());
            }
            //如果返回结果正确则执行
            @Override
            public void onSuccess(GeoBean geoBean) {
                if (Code.OK == geoBean.getCode()) {//getLocationBean
                    String id=geoBean.getLocationBean().get(0).getId();
                    String name=geoBean.getLocationBean().get(0).getName();
                    String adm2=geoBean.getLocationBean().get(0).getAdm2();
                    String adm1=geoBean.getLocationBean().get(0).getAdm1();
                    //因不可以在非ui线程修改ui线程内容,所以必须使用runOnUiThread或类似方法。
                    //直接使用viewname.setText(name);会导致错误,程序退出。
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            viewname.setText(name);
                            viewid.setText(id);
                            viewarea1.setText(adm1);
                            viewarea.setText(adm2);
                        }
                    });
                }else{
                    //在此查看返回数据失败的原因
                    Code code = geoBean.getCode();
                    System.out.println("失败代码: " + code);
                    //Log.i(TAG, "failed code: " + code);
                }
            }
        });
    }
}

动图演示:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/382117.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

公司章程包括了哪些内容

一、公司章程包括了哪些内容 《中华人民共和国公司法》第11条规定&#xff1a;“设立公司必须依法制定公司章程。公司章程对公司、股东、董事、监事、高级管理人员具有约束力。”明确地强调了公司章程对于公司的重要性&#xff0c;公司章程对于公司而言不但是股东合意达成的协…

葵花8号卫星数据简介与下载笔记

1、葵花8号卫星数据简介JMA于2015年7月7日开始运营Himawari-8&#xff0c;以取代MTSAT-2&#xff08;也称为Himawari-7&#xff09;。 Himawari-9号卫星于2017年3月10日开始后备运行。两颗卫星都位于向东约140.7度的轨道上&#xff0c;并将观测东亚和西太平洋区域15年。 源自Hi…

【项目实战】IDEA常用快捷键汇总

一、修改为Eclipse的快捷键 相信很多朋友跟我一样&#xff0c; 都是习惯了eclipse的快捷键&#xff0c;没错&#xff0c;习惯这东西真的很难改&#xff01;IDEA非常强大&#xff0c;支持我们修改IDEA中的keymap为Eclipse的快捷键&#xff01;友好又贴心&#xff0c;有没有&…

大数据框架之Hadoop:MapReduce(四)Hadoop数据压缩

4.1概述 1、压缩概述 压缩技术能够有效减少底层存储系统&#xff08;HDFS&#xff09;读写字节数。压缩提高了网络带宽和磁盘空间的效率。在运行MR程序时&#xff0c;IO操作、网络数据传输、shuffle和Merge要花大量的时间&#xff0c;尤其是数据规模很大和工作负载密集的情况…

3月2日第壹简报,星期四,农历二月十一

3月2日第壹简报&#xff0c;星期四&#xff0c;农历二月十一坚持阅读&#xff0c;静待花开1. 第三次延期&#xff01;财政部&#xff1a;对于购置期在2023年的新能源汽车继续免征车辆购置税。2. 我国2月份制造业PMI为52.6% &#xff0c;创2012年4月以来新高。3. 全国地级市财力…

深入浅出消息队列MSMQ

消息队列MSMQ&#xff0c;相信稍有开发经验的小伙伴都了解一些。开始讲解之前&#xff0c;我们先弄清楚一件事&#xff0c;为什么我们要使用MSMQ&#xff1a; 您可能认为您能够通过一个简单的数据库表(一个应用程序往其中写入数据&#xff0c;另一个应用程序从中读取数据)来应用…

采编式AIGC视频生产流程编排实践

作者 | 百度人工智能创作团队 导读 本文从业务出发&#xff0c;系统介绍了采编式 TTV的实现逻辑和实现路径。结合业务拆解&#xff0c;实现了一个轻量级服务编排引擎&#xff0c;有效实现业务诉求、高效支持业务扩展。 全文6451字&#xff0c;预计阅读时间17分钟。 01 背景 近…

WebRTC之RTP封装与解封装

1 前言rtp_rtcp模块作为Webrtc组件中非常重要的组成部分&#xff0c;首先是对应rtp和rtcp的封装与解封装&#xff0c;第二部分是对QOS各种策略的支持都离不开rtcp的控制协议。这里首先进行协议封装的探讨。2 RTP协议解析各个音视频的大佬对下面这张RTP协议图应该并不陌生&#…

ChatGPT到底是个啥?简析ChatGPT!

目录 ​编辑 1. ChatGPT到底是个啥&#xff1f; 1.1. 简介 1.2 玩法 1.2.1.生成公司理念、生成广告标语 1.2.2.写小说写故事写情书 1.2.3.生成自媒体文案 1.2.4.写代码 2.简析ChatGPT 2.1.ChatGPT核心能力 2.2.ChatGPT进化史 2.2.1.历史沿革 2.2.2.算法 2.3.ChatGPT特…

k8s学习之路 | Pod 基础

文章目录Pod 基础认知什么是 PodPod 的示例 yamlPod 的形式Pod 的多容器协同Pod 的生命周期容器的类型应用容器初始化容器临时容器静态 Pod什么是静态 Pod静态 Pod 位置Pod 探针机制探针类型Probe 配置项探针案例Pod 基础认知 什么是 Pod https://kubernetes.io/zh-cn/docs/c…

Word处理控件Aspose.Words功能演示:使用 Java 合并 MS Word 文档

Aspose.Words 是一种高级Word文档处理API&#xff0c;用于执行各种文档管理和操作任务。API支持生成&#xff0c;修改&#xff0c;转换&#xff0c;呈现和打印文档&#xff0c;而无需在跨平台应用程序中直接使用Microsoft Word。此外&#xff0c; Aspose API支持流行文件格式处…

Overlay网络技术

大家好&#xff0c;我是技福的小咖老师。 Overlay网络是通过网络虚拟化技术&#xff0c;在同一张Underlay网络上构建出的一张或者多张虚拟的逻辑网络。不同的Overlay网络虽然共享Underlay网络中的设备和线路&#xff0c;但是Overlay网络中的业务与Underlay网络中的物理组网和互…

aardio - 【库】简单信息框

昨晚得知aardio作者一鹤的妻子病情严重&#xff0c;深感悲痛。今日给一鹤捐赠少许&#xff0c;望其妻能挺过难关&#xff0c;早日康复。 aardio是一个很好的编程工具&#xff0c;我非常喜欢&#xff0c;这两年也一直在用。虽然未曾用其获利&#xff0c;但其灵活的语法&#xff…

操作系统真相还原——第7章 中断

中断&#xff1a;CPU 暂停正在执行的程序&#xff0c;转而去执行处理该事件的程序&#xff0c;当这段程序执行完毕后&#xff0c; CPU 继续执行刚才的程序。 通常&#xff0c;中断牺牲的是个体的时间&#xff0c;但可以实现多设备的并发&#xff0c;从而提高系统效率 操作系统…

评估Jupyter环境的安全性

评估Jupyter环境的安全性 如何判断您的 Jupyter 实例是否安全&#xff1f; NVIDIA AI 红队开发了一个 JupyterLab 扩展来自动评估 Jupyter 环境的安全性。 jupysec 是一种根据近 100 条规则评估用户环境的工具&#xff0c;这些规则检测配置和工件&#xff0c;这些配置和工件已被…

暴力递归到动态规划

暴力递归到动态规划 假设有排成一行的n个位置&#xff0c; 记为1~n&#xff0c;n-定大于或等于2。开始时机器人在其中的m位置上(m 一定是1~n中的一个)。如果机器人来到1位置&#xff0c;那么下一步只能往右来到2位置&#xff1b;如果机器人来到n位置&#xff0c; 那么下一步只能…

js中splice方法和slice方法

splice方法用来操作数组splice(startIndex,deleteNum,item1,....,)此操作会改变原数组。删除数组中元素参数解释&#xff1a;startIndex为起始index索引。deleteNum为从startIndex索引位置开始需要删除的个数。分三种情况&#xff1a;没有传第三个参数的情况下&#xff0c;dele…

pytest两种生成测试报告的方法——html

pytest有两种生成测试报告的方法&#xff08;html和allure&#xff09;&#xff0c;今天就给大家一介绍下html 一.pytest-html基本语法 1.安装&#xff1a;pip install pytest-html 2.查看版本&#xff1a;pip show pytest-html 3.生成测试报告基本语法&#xff1a; 语法一…

STM32物联网项目之程序框架

前言&#xff1a; 这个系列&#xff0c;我主要写我用32f103实现的各种功能模块&#xff0c;已经程序编写过程中&#xff0c;硬件调试中出现的问题&#xff0c;一边记录&#xff0c;一边分享&#xff0c;一边复盘。 使用的是STM32cubemax&#xff0c;自动生成代码&#xff0c;…

每日学术速递3.2

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.CV 1.Interactive Segmentation as Gaussian Process Classification(CVPR 2023) 标题&#xff1a;作为高斯过程分类的交互式分割 作者&#xff1a;Minghao Zhou, Hong Wang, Qian Zha…