本例程目前只能提供思路,IP自动查询已被封无法访问,科大讯飞的墨迹API已不兼容4.2系统,5.0及以上版本没问题。2023.2.7
好讽刺,本方法已完全不可用了,科大讯飞墨迹api已经用不了了。2023.2.10
android studio版本:2021.2.1
例程:IPfatch_weather(原IPfatch例程出问题了,用不了。)
之前做过一个根据IP地址获取天气的项目。详见:
android根据IP地址自动显示天气(之一)—自动获取IP地址
android根据IP地址自动显示天气(之二)—坑爹的volley和json编码
其实那个还没写完,最近没事想把它写完的时候发现,中华万年历api用不了了,获取不到天气了。只能弃用。
在以网上逛,发现一个“讯飞语音识别内置的墨迹天气API”,可以用,也不知道能用多久,看来以后免费的东西都用不了多久,暂时用着吧。
获取地址:
http://autodev.openspeech.cn/csp/api/v2.1/weather?openId=aiuicus&clientType=android&sign=android&city=上海&latitude=39.902895&longitude=116.427915&needMoreData=true&pageNo=1&pageSize=7
可以获取7天的天气,我只需要3天的,把后面的7改成3就行了。还可以根据城市中文名和经纬度进行定位。这对于无干预获取天气还是很友好的。如要用经纬度获取天气,上面网址中city=后面不要写城市名即可。系统自动匹配经纬度定位。
做这个项目一共需要两个大方面要完成:
1、获得本地经纬度。
2、根据经纬度获取天气。
猎取经纬度还是使用的http://ip-api.com/json/里面可以得到IP,经纬度。
我试了一下,好像只能定位到“市”,再下面的行政单位就不行了,比如如果city=罗湖区,显示的还是深圳的天气,县级市也不行,比如我老家灯塔,显示的是辽阳的天气。也可以了,至少可以用。
具体不多解释,很多技术在之前的文章里都提到过。
具体使用技术:volley,获取数据。json数据解析。其他也没什么。
需要注意,volley依赖可能会有点小麻烦,详见:
android studio 2021.2.1版添加volley依赖失败情况记录
注意加依赖:
implementation 'com.android.volley:volley:1.2.1'
给网络访问权限:
<uses-permission android:name="android.permission.INTERNET"/>
json数据解析详见:
直接上代码(使用的是empty activity):
MainActivity.java
package com.example.ipfatch_weather;
/*
创建日期:2022年10月13日
完成日期:2022年10月13日
功能:1、获取本地IP、经纬度;2、解析json;3、获取天气。4、百度根据IP获取地址已弃用。
获取天气方式:http://autodev.openspeech.cn/csp/api/v2.1/weather?openId=aiuicus&clientType=android&sign=android&city=&latitude=22.5579&longitude=114.065&needMoreData=true&pageNo=1&pageSize=7
城市汉字或者经纬度都可以。有城市名,经纬度无效,如用经纬度定位城市名需为空才行。page size=7为7天天气,改为3为3天天气。
这个是“讯飞语音识别内置的墨迹天气API”7天天气。
*/
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.android.volley.RequestQueue;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONArray;
import org.json.JSONObject;
public class MainActivity extends AppCompatActivity {
private Button get;
private TextView textview;
private TextView cityName;
private TextView weather1;
private Button getWeather;
public String lon;
public String lat;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
get=findViewById(R.id.get);
getWeather=findViewById(R.id.getWeather);
textview=findViewById(R.id.textview);
cityName=findViewById(R.id.city);
weather1=findViewById(R.id.weather);
getPosition();
getWeatherData();
}
public void getPosition()
{
get.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//创建一个请求队列
RequestQueue requestQueue=Volley.newRequestQueue(MainActivity.this);
//创建一个请求
String url="http://ip-api.com/json/";//得到本机IP,英文城市名或经纬度。本例使用经纬度定位。
//通过百度api把IP解析成中文地址。
//String url="http://api.map.baidu.com/location/ip?ak=pXbQRnMzrXDOr33U2h3WVFaxN4NeM9QQ&ip=115.45.169.246&coor=bd09ll";
StringRequest stringRequest=new StringRequest(url, new com.android.volley.Response.Listener<String>() {
//正确接受数据之后的回调
@Override
public void onResponse(String response) {
analyzeJSONArray(response);
}
}, new com.android.volley.Response.ErrorListener() {//发生异常之后的监听回调
@Override
public void onErrorResponse(VolleyError error) {
textview.setText("加载错误"+error);
}
});
//将创建的请求添加到请求队列当中
requestQueue.add(stringRequest);
}
});
}
public void analyzeJSONArray(String json) {
try {
JSONObject jsonObjectALL = new JSONObject(json);
String status=jsonObjectALL.getString("status");
lat = jsonObjectALL.getString("lat");
lon =jsonObjectALL.getString("lon");
textview.setText(status);
System.out.println(lat);
System.out.println(lon);
} catch (Exception e) {
e.printStackTrace();
}
}
public void getWeatherData()
{
getWeather.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//创建一个请求队列
RequestQueue requestQueue=Volley.newRequestQueue(MainActivity.this);
//创建一个请求
String url="http://autodev.openspeech.cn/csp/api/v2.1/weather?openId=aiuicus&clientType=android&sign=android&city=&latitude="+lat+"&longitude="+lon+"&needMoreData=true&pageNo=1&pageSize=3";//请求地址
//通过百度api把IP解析成中文地址。
//String url="http://api.map.baidu.com/location/ip?ak=pXbQRnMzrXDOr33U2h3WVFaxN4NeM9QQ&ip=115.45.169.246&coor=bd09ll";
StringRequest stringRequest=new StringRequest(url, new com.android.volley.Response.Listener<String>() {
//正确接受数据之后的回调
@Override
public void onResponse(String response) {
analyzeWeatherJSON(response);
}
}, new com.android.volley.Response.ErrorListener() {//发生异常之后的监听回调
@Override
public void onErrorResponse(VolleyError error) {
textview.setText("加载错误"+error);
}
});
//将创建的请求添加到请求队列当中
requestQueue.add(stringRequest);
}
});
}
public void analyzeWeatherJSON(String json) {
try {
JSONObject jsonObjectALL = new JSONObject(json);
JSONObject jsonObject1=jsonObjectALL.getJSONObject("data");
JSONArray jsonArray=jsonObject1.getJSONArray("list");
JSONObject jsonObject2 = jsonArray.getJSONObject(0);
String city = jsonObject2.getString("city");
String weather=jsonObject2.getString("weather");
cityName.setText(city);
weather1.setText(weather);
} catch (Exception e) {
e.printStackTrace();
}
}
}
main_activity.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/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="显示是否成功"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:textSize="30sp"
app:layout_constraintVertical_bias="0.344" />
<Button
android:id="@+id/get"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="108dp"
android:text="获取经纬度"
android:textSize="30sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/getWeather"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="解析天气"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.536"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.533" />
<TextView
android:id="@+id/city"
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.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:textSize="30sp"
app:layout_constraintVertical_bias="0.658" />
<TextView
android:id="@+id/weather"
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.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:textSize="30sp"
app:layout_constraintVertical_bias="0.785" />
</androidx.constraintlayout.widget.ConstraintLayout>
动图展示: