Android studio 百度地圖開發(5)查詢周邊服務(加油站)


Android studio 百度地圖開發(5)查詢周邊服務(加油站)

email:chentravelling@163.com

      開發環境:win7 64位,Android Studio,請注意是Android Studio,使用的導航SDK版本:3.1.0

一.功能描述

      大致功能為:通過百度地圖定位獲得當前位置,然后通過加油站數據接口(https://www.juhe.cn/docs/api/id/7)搜索周邊的加油站信息,並在地圖上顯示。這里,我把訪問加油站數據接口的部分放在了服務器上,因為后期還有一些其他功能,不可能都放在手機端去實現。

二.實現部分

1.加油站數據接口

       需要先申請api_key,很簡單,沒有百度地圖的API_KEY那么復雜,地址:https://www.juhe.cn/docs/api/id/7。

2.搭建服務器

      這部分,本人不知道怎么去描述,因為有web基礎,使用過SSM(spring+springMVC+Mybatis)架構,所以還是繼續使用SSM。關於SSM架構的服務器環境搭建,資料很多,就不贅述了,而且,主要功能並不在於服務器上,換一個架構甚至“沒有架構”都行。

       在服務器端主要要實現對加油站數據的訪問,按照官方的API說明,通過以下代碼實現了數據訪問:

package com.intveh.component.gas.controller;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.intveh.component.car.model.Car;

@Controller
public class GasController {
public static final String DEF_CHATSET = "UTF-8";
public static final int DEF_CONN_TIMEOUT = 30000;
public static final int DEF_READ_TIMEOUT = 30000;
public static String userAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36";
/**
* 請求接口地址
*/
public static String url = "http://apis.juhe.cn/oil/local";
/**
* AppKey
*/
public static String key = "cbee44f8a21c371***********51e8b9";//改為自己的key
/**
* 查詢附近的加油站
*
* @param 經緯度
*
* @return 查詢結果 json
*/
@RequestMapping(value = "/gas/searchNear")
@ResponseBody
public void searchNear(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
//response.setHeader("Access-Control-Allow-Origin", "*");
//Car car = carDAO.getCar(carId);
//return car;
String result = "";
//System.out.println("開始搜索");
/**
* 緯度
*/
String latitude = request.getParameter("latitude");
/**
* 經度
*/
String longitude = request.getParameter("longitude");
/**
* 搜索范圍
*/
String radius = request.getParameter("radius")==null?"1000":request.getParameter("radius");
/**
* 頁數
*/
String page = "1";
/**
* 格式
*/
String format = "1";
//System.out.println(longitude+","+latitude+","+radius+","+page+","+format);
Map params = new HashMap();
if(latitude!=null&&longitude!=null&&!"".equals(latitude)&&!"".equals(longitude))
{
params.put("lon", longitude);
params.put("lat", latitude);
params.put("r", radius);
params.put("page", page);
params.put("format",format);
params.put("key", key);
JSONObject object = new JSONObject();
//System.out.println(longitude+","+latitude+","+radius+","+page+","+format);
try
{
result =net(url, params, "GET");
object = JSONObject.fromObject(result);
if(object.getInt("error_code")==0){
System.out.println(object.get("result"));

}else{
System.out.println(object.get("error_code")+":"+object.get("reason"));
}

response.setContentType("text/json; charset=UTF-8");
response.getOutputStream().write(object.get("result").toString().getBytes("UTF-8"));
//System.out.println(object.get("result"));
} catch (Exception e) {
e.printStackTrace();
}
//response.setHeader("Access-Control-Allow-Origin", "*");
//response.reset();
//response.setContentType(String);

//response.getOutputStream().write(object.toString().getBytes("UTF-8"));
}
}
/**
*
* @param strUrl 請求地址
* @param params 請求參數
* @param method 請求方法
* @return 網絡請求字符串
* @throws Exception
*/
public static String net(String strUrl, Map params,String method) throws Exception {
HttpURLConnection conn = null;
BufferedReader reader = null;
String rs = null;
try {
StringBuffer sb = new StringBuffer();
if(method==null || method.equals("GET")){
strUrl = strUrl+"?"+urlencode(params);
}
URL url = new URL(strUrl);
System.out.println("url = "+url);
conn = (HttpURLConnection) url.openConnection();
if(method==null || method.equals("GET")){
conn.setRequestMethod("GET");
}else{
conn.setRequestMethod("POST");
conn.setDoOutput(true);
}
conn.setRequestProperty("User-agent", userAgent);
conn.setUseCaches(false);
conn.setConnectTimeout(DEF_CONN_TIMEOUT);
conn.setReadTimeout(DEF_READ_TIMEOUT);
conn.setInstanceFollowRedirects(false);
conn.connect();
/* if (params!= null && method.equals("POST")) {
try (DataOutputStream out = new DataOutputStream(conn.getOutputStream())) {
out.writeBytes(urlencode(params));
}
}*/
InputStream is = conn.getInputStream();
reader = new BufferedReader(new InputStreamReader(is, DEF_CHATSET));
String strRead = null;
while ((strRead = reader.readLine()) != null) {
sb.append(strRead);
}
rs = sb.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
reader.close();
}
if (conn != null) {
conn.disconnect();
}
}
return rs;
}

//將map型轉為請求參數型
public static String urlencode(Map<String,Object>data) {
StringBuilder sb = new StringBuilder();
for (Map.Entry i : data.entrySet()) {
try {
sb.append(i.getKey()).append("=").append(URLEncoder.encode(i.getValue()+"","UTF-8")).append("&");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return sb.toString();
}
}
      使用一下數據訪問服務器即可查看獲得的加油站信息:


3.手機端實現

      (對於我)稍微有點難度的還是在手機端功能的實現。

第一步:加油站信息類GasStationModel.java

      為了更加方便的傳遞數據,寫了一個加油站信息類,對數據實體化。同時實現了Serializable接口,因為后面需要利用intent傳遞list<GasStationModel>時,將list強制轉化成serializable。

package intvehapp.intvehapp;

import java.io.Serializable;
import java.util.Map;

/**
* Created by chen on 2016/4/2.
*/
public class GasStationModel implements Serializable {

public GasStationModel(
String area,
String fwlsmc,
String address,
String areaname,
String distance,
String exhaust,
String discount,
String lon,
String brandname,
String type,
Map<String,String> price,
Map<String,String> gastprice,
String name,
String id,
String lat,
String position)
{
this.area = area;
this.address = address;
this.areaname = areaname;
this.brandname = brandname;
this.discount = discount;
this.distance = distance;
this.exhaust = exhaust;
this.fwlsmc = fwlsmc;
this.gastprice = gastprice;
this.id = id;
this.price = price;
this.lon = lon;
this.type = type;
this.name = name;
this.lat = lat;
this.position = position;
}
/**
* 郵編
*/
private String area;
/**
* 加油卡信息
*/
private String fwlsmc;
/**
* 加油站地址
*/
private String address;
/**
* 城市區域
*/
private String areaname;
/**
* 距離?
*/
private String distance;
/**
* 尾氣排放標准
*/
private String exhaust;
/**
* 是否打折加油站
*/
private String discount;
/**
* 百度地圖經度
*/
private String lon;
/**
* 運營商類型
*/
private String brandname;
/**
* 加油站類型
*/
private String type;
/**
* 省控基准油價
*/
private Map<String,String> price;
/**
* 加油站油價
*/
private Map<String,String> gastprice;
/**
* 加油站名字
*/
private String name;
/**
* id
*/
private String id;
/**
* 谷歌地圖坐標
*/
private String position;
/**
* 百度地圖緯度
*/
private String lat;

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getArea() {
return area;
}

public void setArea(String area) {
this.area = area;
}
public String getFwlsmc() {
return fwlsmc;
}

public void setFwlsmc(String fwlsmc) {
this.fwlsmc = fwlsmc;
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

public String getAreaname() {
return areaname;
}

public void setAreaname(String areaname) {
this.areaname = areaname;
}

public String getDistance() {
return distance;
}

public void setDistance(String distance) {
this.distance = distance;
}

public String getDiscount() {
return discount;
}

public void setDiscount(String discount) {
this.discount = discount;
}

public String getExhaust() {
return exhaust;
}

public void setExhaust(String exhaust) {
this.exhaust = exhaust;
}

public String getLon() {
return lon;
}

public void setLon(String lon) {
this.lon = lon;
}

public String getBrandname() {
return brandname;
}

public void setBrandname(String brandname) {
this.brandname = brandname;
}

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public Map<String, String> getPrice() {
return price;
}

public void setPrice(Map<String, String> price) {
this.price = price;
}

public Map<String, String> getGastprice() {
return gastprice;
}

public void setGastprice(Map<String, String> gastprice) {
this.gastprice = gastprice;
}

public String getPosition() {
return position;
}

public void setPosition(String position) {
this.position = position;
}

public String getLat() {
return lat;
}

public void setLat(String lat) {
this.lat = lat;
}
}

第二步:新建線程訪問數據,通過handler與主線程通信。

      一開始,直接在主線程中訪問服務器,最終發現失敗了,查閱了資料后才知道:android4.0以后的版本,主線程(UI線程)不在支持網絡請求,原因大概是影響主線程,速度太慢,容易卡機,所以需要開啟新的線程請求數據。

 /**
* 通過handler與主線程通信
*/
final Handler handler = new Handler()
{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Bundle data = msg.getData();
String err = data.getString("err");
/**
* 查詢成功
*/
if("0".equals(err))
{
List<GasStationModel> listGasStation = (List<GasStationModel> )data.getSerializable("listGasStation");
Toast.makeText(BaiDuMapActivity.this, "查詢成功"+listGasStation.size(), Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(BaiDuMapActivity.this, "附近沒有加油站信息", Toast.LENGTH_LONG).show();
}
//Log.i("mylog", "請求結果為-->" + val);
// TODO
// UI界面的更新等相關操作
}
};
/**
* 開啟一個新的線程,訪問服務器
* 當有數據返回時,通過handler傳遞消息
*/

new Thread(new Runnable() {
@Override
public void run() {
//請求數據
List<GasStationModel> listGasStation = ConnectServer.searchNearGas(params);
//發送消息
Message message = new Message();
Bundle bundle = new Bundle();
if(listGasStation!=null)
{
bundle.putSerializable("listGasStation", (Serializable) listGasStation);
bundle.putString("err","0");//成功
}
else
bundle.putString("err","1");//失敗
message.setData(bundle);
handler.sendMessage(message);
}
}).start();

第三步:ConnectServer.java訪問服務器類

       考慮到后期對服務器訪問還會很多,所以就單獨建了一個訪問服務器的類。

       實現對服務器的訪問,搜索周邊加油站。

/**
* Created by chen on 2016/4/2.
*/
public class ConnectServer {


public static List<GasStationModel> searchNearGas(Map<String, String> params)
{
/**
* 請求地址
*/
String path = serverURL+"gas/searchNear?key="+key+"&";
/**
* 添加參數
*/
List<GasStationModel> listGasStation = new ArrayList<GasStationModel>();
try {
StringBuilder url = new StringBuilder(path);
URL nURL = new URL("http://www.baidu.com");
//url.append("?");
for (Map.Entry<String, String> entry : params.entrySet()) {
url.append(entry.getKey()).append("=");
url.append(URLEncoder.encode(entry.getValue(), "UTF-8"));// 編碼
url.append('&');
}
url.deleteCharAt(url.length() - 1);
HttpURLConnection connection = (HttpURLConnection) new URL(
url.toString()).openConnection();
//HttpURLConnection connection = (HttpURLConnection) nURL.openConnection();
connection.setConnectTimeout(5000);
connection.setRequestMethod("GET");


String result = "";
InputStream in = connection.getInputStream();
try {
Thread.sleep(300);
result = read(connection.getInputStream());
} catch (InterruptedException e) {
e.printStackTrace();
}

/**
* 解析JSON數據等等<span style="font-family:Microsoft YaHei;">操作</span>
*/

}
}catch (Exception e )
{
e.printStackTrace();
}
return listGasStation;
}
private static String read(InputStream in) throws Exception {
byte[] data;

int length = in.available();
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte[]buf = new byte[1024];
int len = 0;

while((len = in.read(buf))!=-1){
bout.write(buf, 0, len);

}
data = bout.toByteArray();
return new String(data,"UTF-8");
}
}

三.效果與分析


       其實整個流程的思路還是很簡單:定位獲取當前數據->訪問加油站數據接口獲得周邊加油站位置信息->回調,在地圖上顯示。但是,實現起來有些地方還是很費心,比如手機端接收數據不完整的情況。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com