Android几个常用框架合集(SmartRefreshLayout,EventBus,Glide,Gson,OkHttp,百度地图)

一、SmartRefreshLayout

传统Adapter的优化

  • 回顾ListView配合Adapter显示数据

布局中设置ListView控件

​ 设计Item子布局

​ 自定义Adapter并重写getView()等方法

​ 加载子布局页面及控件

​ 给控件绑定数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0bMWvNMs-1610011416462)(Android综合应用.assets/image-20201104154050119.png)]

重复创建,效率低下

  • 解决方式

在继承BaseAdapter的自定义类里面创建一个内部类

static class ViewHolder{
    private TextView tvName;
    private TextView tvInfo;
}

起到缓存View的目的,避免重复创建

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder = null;
    if(null == convertView) {
        //加载item布局文件,赋值给convertView
        convertView = LayoutInflater.from(context)
                .inflate(layout, null);
        holder = new ViewHolder();
        //创建Item中的控件对象
        holder.tvName = convertView.findViewById(R.id.tv_name);
        holder.tvInfo = convertView.findViewById(R.id.tv_info);
        //在convertView中缓存holder对象
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }
    //给控件对象赋值
    Student stu = stus.get(position);
    holder.tvName.setText(stu.getName());
    holder.tvInfo.setText(stu.getInfo());
    return convertView;
}

SmartRefreshLayout控件的使用

  • 使用步骤

第一步:导入依赖:

//添加SmartRefreshLayout依赖
implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0'
implementation 'com.scwang.smartrefresh:SmartRefreshHeader:1.1.1'

第二步:添加智能刷新控件(可自己设计刷新头和刷新尾样式)

<com.scwang.smartrefresh.layout.SmartRefreshLayout
    android:id="@+id/srl"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!--自定义Header样式-->
    <pl.droidsonroids.gif.GifImageView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:src="@mipmap/eat"/>
    <ListView
        android:id="@+id/lv_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</com.scwang.smartrefresh.layout.SmartRefreshLayout>

设置刷新样式

  • 方式一:全局方式

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7nBbd2ie-1610011416465)(Android综合应用.assets/image-20201104155643278.png)]

public class MyApplication extends Application {
    static {
        //设置Header样式
        SmartRefreshLayout.setDefaultRefreshHeaderCreator(
                new DefaultRefreshHeaderCreator() {
                    @NonNull
                    @Override
                    public RefreshHeader createRefreshHeader(@NonNull Context context, @NonNull RefreshLayout layout) {
                        //创建Header样式
                        BezierRadarHeader header =
                                new BezierRadarHeader(context);
                        return header;
                    }
                }
        );
        //设置Footer样式
        SmartRefreshLayout.setDefaultRefreshFooterCreator(
                new DefaultRefreshFooterCreator() {
                    @NonNull
                    @Override
                    public RefreshFooter createRefreshFooter(@NonNull Context context, @NonNull RefreshLayout layout) {
                        //实例化一种Footer样式
                        FalsifyFooter footer =
                                new FalsifyFooter(context);
                        return footer;
                    }
                }
        );
    }
}
  • 方式二:XML方式
<com.scwang.smartrefresh.layout.SmartRefreshLayout
    android:id="@+id/srl"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.scwang.smartrefresh.layout.header.ClassicsHeader
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
            <ListView
                android:id="@+id/lv_content"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
    <com.scwang.smartrefresh.layout.footer.BallPulseFooter
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</com.scwang.smartrefresh.layout.SmartRefreshLayout>
  • 方式三:java方式
//设置 Header 为 贝塞尔雷达 样式
refreshLayout.setRefreshHeader(new BezierCircleHeader(this)).setHorizontalFadingEdgeEnabled(true);        
//设置 Footer 为 球脉冲 样式
refreshLayout.setRefreshFooter(new BallPulseFooter(this).setSpinnerStyle(SpinnerStyle.Scale));

三种方式优先级:java>xml>application

第三步:给智能刷新控件设置监听器

//给智能刷新控件注册下拉刷新事件监听器
refreshLayout.setOnRefreshListener(new OnRefreshListener() {
    @Override
    public void onRefresh(@NonNull RefreshLayout refreshLayout) {
        refreshData();
        refreshLayout.finishRefresh();
    }
});
//给智能刷新控件注册上拉加载更多事件监听器
refreshLayout.setOnLoadMoreListener(new onl oadMoreListener() {
    @Override
    public void onl oadMore(@NonNull RefreshLayout refreshLayout) {
        //加载更多数据(假设超过10条数据则加载完毕)
        if(stus.size() < 10) {
            loadMoreData();
            //通知加载数据完毕
            refreshLayout.finishLoadMore();
        } else {
            //通知没有更多数据可加载
            refreshLayout.finishLoadMoreWithNoMoreData();
        }
    }
});

二、EventBus

传统页面跳转实现(带返回值)

Intent intent = new Intent();
//设置目的地Activity类
intent.setClass(MainActivity.this,NewActivity.class);
//跳转时需要携带数据
intent.putExtra("name", names[position]);
intent.putExtra("phone", "1234565");
intent.putExtra("email", "123132ees");
intent.putExtra("position",position);
startActivityForResult(intent,LOGIN_REQUEST);

//接收返回的响应数据,并且刷新界面
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    //requestCode跳转时的请求码
    //resultCode返回响应的结果码
    //data返回响应的Intent对象
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == LOGIN_REQUEST && resultCode == 200){
        //获得从NewActivity响应的数据
        String name = data.getStringExtra("name");
        //修改数据源
        names[currentPosition]=name;
        //刷新ListView
        adapter.notifyDataSetChanged();
    }
}

EventBus的使用

  • 类似访问者/订阅者模式,EventBus包含3个元素

时间,订阅者,发布者

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RNpclaVP-1610011416466)(Android综合应用.assets/image-20201104162520610.png)]

  • 两种事件类型:普通事件、粘性事件

两种事件的区别:

1)相同点:都必须要注册EventBus

2)普通事件只有注册以后发布的事件才能收到,粘性事件可以收到注册前发布的粘性事件;订阅了粘性事件后也可以收到普通的事件

  • 用法

第一步:导入依赖

implementation 'org.greenrobot:eventbus:3.2.0'

第二步:获取EventBus对象

EventBus eventBus = EventBus.getDefault();

第三步:注册EventBus

eventBus.register(MainActivity.this);
//取消注册
//eventBus.unregister(MainActivity.this);

第四步:定义事件类

/**
 * 自定义EventBus事件
 */
public class MyEvent {
    private String msg;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    @Override
    public String toString() {
        return "MyEvent{" +
                "msg='" + msg + '\'' +
                '}';
    }
}

第五步:发布事件

//定义事件对象
MyEvent event = new MyEvent();
event.setMsg("天气晴朗,出来晒被子了");
//发布事件
EventBus.getDefault().post(event);

//粘性事件
EventBus.getDefault().postSticky(event);

//移除粘性事件
//removeStickyEvent(事件)
//移除所有粘性事件                        
//removeAllStickyEvents()

第六步:订阅者编写事件回调方法

//订阅普通事件,只能接收普通事件
@Subscribe  
//订阅粘性事件后可以接收到注册EventBus前发布的粘性事件
//@Subscribe(sticky = true, threadMode = ThreadMode.ASYNC)
public void onEvent(MyEvent event){
    tvMsg.setText(event.getMsg());
}

五种线程模式

1)POSTING:事件回调方法的执行在发布事件的线程中

2)MAIN:事件回调方法的执行在主线程中

3)MAINORDERED:事件回调方法的执行在主线程的事件队列

4)BACKGROUND:事件回调方法的执行在后台线程中

5)ASYNC:事件回调方法的执行在后台单独的一个线程中,可以用来执行耗时任务

三、Glide

Glide用法

第一步:引入依赖

implementation 'com.github.bumptech.glide:glide:4.11.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'

第二步:添加权限

<!--如果需要加载网络图片-->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name= "android.permission.ACCESS_NETWORK_STATE"/>
<!--要从本地文件夹或 DCIM 或图库中加载图片-->
<uses-permission android:name= "android.permission.READ_EXTERNAL_STORAGE" />
<!--如果要将 Glide 的缓存存储到SD 卡上-->
<uses-permission android:name= "android.permission.WRITE_EXTERNAL_STORAGE" />

第三步:加载图片

  • 加载网络图片
String imgUrl = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1603099775034&di=74dce1068c65de1a0d869e69906eb507&imgtype=0&src=http%3A%2F%2Fa0.att.hudong.com%2F56%2F12%2F01300000164151121576126282411.jpg";
Glide.with(this).load(imgUrl).into(ivImg);
  • 加载一个网络动图
String imgUrl = "https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=3278720085,289405952&fm=26&gp=0.jpg";
Glide.with(this).asGif().load(gifImg).into(ivImg);
  • 加载Assets目录下的图片
try {
    //将Assets目录的图片解析成Bitmap
    AssetManager assets = getAssets();
    InputStream in = assets.open("notexist.jpg");
    Bitmap bitmap = BitmapFactory.decodeStream(in);
    //使用Glide框架加载Bitmap
    Glide.with(this).load(bitmap).into(ivImg);
} catch (IOException e) {
    e.printStackTrace();
}
  • 加载raw目录下的图片
Glide.with(this).load(R.raw.man).into(ivImg);
  • 设置占位符的请求选项,加载网络图片
String url = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1603101761728&di=721ae5232e882c8cf1f247355b4cf068&imgtype=0&src=http%3A%2F%2Fa0.att.hudong.com%2F70%2F91%2F01300000261284122542917592865.jpg";
Glide.with(this)
        .load(url)
        .circleCrop()//转换策略,特别适合头像的显示
//                .fitCenter()
//                .centerCrop()
        .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)//默认磁盘缓存策略
//                .diskCacheStrategy(DiskCacheStrategy.NONE)//不缓存
        .placeholder(R.mipmap.loading)//正在加载时显示的图片
        .error(R.mipmap.failure)//永久加载失败时显示的图片
        .fallback(R.mipmap.notexist)//表示图片地址为null时显示的图片
        .into(ivImg);
  • GeneratedAPI
GlideApp.with(this)
    .asGif()
    .load("https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=3278720085,289405952&fm=26&gp=0.jpg")
    .placeholder(R.mipmap.loading)
    .circleCrop()
    .diskCacheStrategy(DiskCacheStrategy.DATA)
    .into(ivImg);

四、Gson

Gson的用法

Grade

public class Grade {
    private String gName;

    public String getgName() {
        return gName;
    }

    public void setgName(String gName) {
        this.gName = gName;
    }

    @Override
    public String toString() {
        return "Grade{" +
                "gName='" + gName + '\'' +
                '}';
    }
}

Student

public class Student {
    private String name;
    private int age;
    private transient String transientProp;
    private static String college;
    private Grade grade;
    private Date birthday;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getTransientProp() {
        return transientProp;
    }

    public void setTransientProp(String transientProp) {
        this.transientProp = transientProp;
    }

    public static String getCollege() {
        return college;
    }

    public static void setCollege(String college) {
        Student.college = college;
    }

    public Grade getGrade() {
        return grade;
    }

    public void setGrade(Grade grade) {
        this.grade = grade;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", birthday=" + birthday +
                ", transientProp='" + transientProp + '\'' +
                ", college=" + college +
                ", grade=" + grade +
                '}';
    }
}

第一步:导入依赖

implementation 'com.google.code.gson:gson:2.8.6'

第二步:初始化Gson对象(new方法)

Gson gson = new Gson();
gson.toJson(1);            // ==> 1
gson.toJson("abcd");       // ==> "abcd"
gson.toJson(new Long(10)); // ==> 10
int[] values = { 1 };
gson.toJson(values);       // ==> [1]

第二步:初始化Gson对象(GsonBuilder)

Gson gson = new GsonBuilder()//创建GsonBuilder对象
    .setPrettyPrinting()//格式化输出
    .serializeNulls()//允许输出Null值属性
    .setDateFormat("YY:MM:dd")//日期格式化
    .create();//创建Gson对象

第三步:Gson串操作

  • 普通对象

序列化

//实例化Student对象
Student student = new Student();
student.setName("July");
student.setAge(20);
student.setTransientProp("transient属性");
student.setCollege("软件学院");
//student对象序列化
String json = gson.toJson(student);
//显示Json串到文本框
tvJson.setText(json);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SrBZ21Q6-1610011416468)(Android综合应用.assets/image-20201104170625484.png)]

​ 为什么显示为null值呢???

​ 因为javaBean属性中出现transient和static修饰,Gson是不会序列化的,所以显示为null

反序列化

//得到Json串
String json = tvJson.getText().toString();
//对Json串反序列化
Student student = gson.fromJson(json, Student.class);
//把反序列化后的对象显示在文本框
tvObj.setText(student.toString());

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bmF3jrU8-1610011416469)(Android综合应用.assets/image-20201104171457564.png)]

  • 嵌套类的对象

序列化

Student stu = new Student();
stu.setName("李雷");
stu.setAge(18);
stu.setBirthday(new Date());
Grade grade = new Grade();
grade.setgName("Android");
stu.setGrade(grade);
//序列化
String json = gson.toJson(stu);
tvJson.setText(json);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-usWLpwrg-1610011416470)(Android综合应用.assets/image-20201104171624388.png)]

反序列化

String json = tvJson.getText().toString();
//反序列化
Student stu = gson.fromJson(json, Student.class);
tvObj.setText(stu.toString());

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ps4GypuZ-1610011416471)(Android综合应用.assets/image-20201104171634863.png)]

  • 对象数组

序列化

Student[] stus = new Student[1];
Student stu = new Student();
stu.setName("李雷");
stu.setAge(18);
stu.setBirthday(new Date());
Grade grade = new Grade();
grade.setgName("Android");
stu.setGrade(grade);
stus[0] = stu;
//序列化
String json = gson.toJson(stus);
tvJson.setText(json);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ExSICa4j-1610011416471)(Android综合应用.assets/image-20201104171952309.png)]

反序列化

String json = tvJson.getText().toString();
//反序列化
Student[] stus = gson.fromJson(json, Student[].class);
for(int i = 0; i < stus.length; i++){
    tvObj.setText(stus[i].toString() + ";" + tvObj.getText().toString());
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kz84eliX-1610011416472)(Android综合应用.assets/image-20201104172000373.png)]

  • 对象集合

序列化

List<Student> stus = new ArrayList<>();
Student stu1 = new Student();
stu1.setName("李雷");
stu1.setAge(18);
stus.add(stu1);
Student stu2 = new Student();
stu2.setName("韩梅梅");
stu2.setAge(18);
stus.add(stu2);
//序列化
String json = gson.toJson(stus);
tvJson.setText(json);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vuoGWd2a-1610011416473)(Android综合应用.assets/image-20201104172111626.png)]

反序列化

String json = tvJson.getText().toString();
//反序列化
//1. 得到集合的类型
Type type = new TypeToken<List<Student>>(){}.getType();
//2. 反序列化
List<Student> stus = gson.fromJson(json, type);
tvObj.setText(stus.toString());

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oE42nlKb-1610011416474)(Android综合应用.assets/image-20201104172117409.png)]

五、OkHttp

OkHttp使用方法

  • 同步和异步的区别:

    同步方式是发送请求后,就会进入阻塞状态,直到收到响应。同一时刻只能有一个任务发起,synchronized关键字锁住了整个代码,如果当前OkhttpClient已经执行了一个同步任务,如果这个任务没有释放锁,那么新发起的请求将被阻塞,直到当前任务释放锁

    异步方式是在回调中处理响应的,同一时刻可以发起多个请求,因为异步请求每一个都是在一个独立的线程,由两个队列管理,并且synchronized只锁住了代码校验是否执行的部分。

  • OKhttp中请求任务的管理是由dispatcher负责的,负责请求的分发和发起。实际执行请求的是ConnctionPool。

第一步:导入依赖

implementation 'com.squareup.okhttp3:okhttp:4.9.0'

第二步:创建OkHttpClient对象(new)

OkHttpClient okHttpClient = new OkHttpClient();

第二步:创建OkHttpClient对象(Bulder)

okHttpClient = new OkHttpClient.Builder()
        //可以添加网络请求参数,如网络超时连接时间等
        .build();

无参数的同步的Get请求

第三步:创建Request请求对象

Request.Builder reqBuilder = new Request.Builder();
//设置Builder参数
reqBuilder.url("http://www.baidu.com");
//通过Builder对象创建Request对象
Reqsuet request = reqBuilder.build();

第四步:创建Call对象

Call call = okHttpClient.newCall(request);

第五步:发起请求并获取响应(同步)

try {
    Response response = call.execute();
    //获取响应中的内容
    ResponseBody body = response.body();
    //获取响应中包含的字符串信息
    String result = body.string();
    Log.i("phz", result);
} catch (IOException e) {
    e.printStackTrace();
}

url末尾带参数的异步的get请求

第三步:创建请求对象

Request request = new Request.Builder()
    .url(ServerConfig.SERVER_HOME
         + "WithNoParamRequest?info=签到")
    .build();

第四步:创建call对象

Call call = okHttpClient.newCall(request);

第五步:异步方式提交请求并获取响应

call.enqueue(new Callback() {
    @Override
    public void onFailure(@NotNull Call call, @NotNull IOException e) {
        Log.i("phz", "请求失败");
    }

    @Override
    public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
        //获取服务端返回的数据(假设是字符串)
        String result = response.body().string();
        Log.i("phz", result);

        //通知界面信息改变
        Message msg = handler.obtainMessage();
        msg.what = 1;
        msg.obj = result;
        handler.sendMessage(msg);
    }
});

使用POST方式提交Form表单数据

第三步:创建Request请求对象(提前准备好Form表单数据封装)

//创建FormBody对象
FormBody formBody =
        new FormBody.Builder()
        .add("name", "张三")
        .add("course", "Android综合应用")
        .build();
//创建请求对象
Request request = new Request.Builder()
        .url(ServerConfig.SERVER_HOME + "WithFormParamRequest")
//                .method("POST", formBody)
        .post(formBody)
        .build();

第四步:创建call对象

Call call = okHttpClient.newCall(request);

第五步: 提交请求并获取响应

try {
    Response response = call.execute();
    //获取响应的字符串信息
    String result = response.body().string();

    Message msg = handler.obtainMessage();
    msg.what = 1;
    msg.obj = result;
    handler.sendMessage(msg);
} catch (IOException e) {
    e.printStackTrace();
}

提交普通字符串数据

第三步:创建Request对象

//1) 使用RequestBody封装请求数据
//获取待传输数据对应的MIME类型
MediaType type = MediaType.parse("text/plain");
//创建RequestBody对象
RequestBody reqBody = RequestBody.create(
        "{'name':'李四','course':'Android'}",
        type
);
//2) 创建请求对象
Request request = new Request.Builder()
        .url(ServerConfig.SERVER_HOME + "JsonStringParamRequest")
        .post(reqBody)
        .build();

第四步:创建CALL对象

Call call = okHttpClient.newCall(request);

第五步:提交请求并获取响应

//4. 提交请求并获取响应
call.enqueue(new Callback() {
    @Override
    public void onFailure(@NotNull Call call, @NotNull IOException e) {
        Log.i("phz", "请求失败");
    }

    @Override
    public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
        String result = response.body().string();

        Message msg = handler.obtainMessage();
        msg.what = 1;
        msg.obj = result;
        handler.sendMessage(msg);
    }
});

从本地files目录下上传一个PDF文件给服务器

第三步:创建请求对象

//获取待上传的pdf文件
String pdf = getFilesDir().getAbsolutePath() + "/test.pdf";
File file = new File(pdf);
//获取待上传文件的MIME类型
MediaType type = MediaType.parse("application/pdf");
//创建RequestBody对象,并封装数据
RequestBody reqBody = RequestBody.create(
        file,//待上传的数据
        type //数据对应的MIME类型
);
Request request = new Request.Builder()
        .url(ServerConfig.SERVER_HOME + "UpPDFRequest")
        .post(reqBody)
        .build();

第四步:创建CALL对象

Call call = okHttpClient.newCall(request);

第五步:异步方式提交请求并获取响应

call.enqueue(new Callback() {
    @Override
    public void onFailure(@NotNull Call call, @NotNull IOException e) {
        Log.i("phz", "请求失败");
    }

    @Override
    public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
        //获取服务端返回的数据
        String result = response.body().string();

        //使用handler将数据封装在Message中,并发布出去,以备显示在UI控件中
        Message msg = handler.obtainMessage();
        msg.what = 1;
        msg.obj = result;
        handler.sendMessage(msg);
    }
});

从服务端下载图片

第三步:创建请求对象

Request request = new Request.Builder()
        .url(ServerConfig.SERVER_HOME + "DownLoadImgRequest")
        .build();

第四步: 创建CALL对象

Call call = okHttpClient.newCall(request);

第五步:发起异步请求并获取响应

call.enqueue(new Callback() {
    @Override
    public void onFailure(@NotNull Call call, @NotNull IOException e) {
        Log.i("phz", "请求图片失败");
    }

    @Override
    public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
        //获取服务端返回的网络输入流
        InputStream in = response.body().byteStream();
        //第1种:获取本地文件输出流,经过流的循环读写实现图片拷贝
        //第2种:通过BitmapFactory将输入流解析成一个Bitmap对象
        Bitmap bitmap = BitmapFactory.decodeStream(in);
        //通过Message发布
        Message msg = handler.obtainMessage();
        msg.what = 2;
        msg.obj = bitmap;
        handler.sendMessage(msg);
    }
});

从服务端获取图片资源路径,使用Glide框架显示图片

第三步:创建请求对象

Request request = new Request.Builder()
        .url(ServerConfig.SERVER_HOME + "DownLoadImgNameRequest")
        .build();

第四步:创建CALL对象

Call call = okHttpClient.newCall(request);

第五步:发起请求获取网络路径

try {
    Response response = call.execute();
    String img = response.body().string();

    Message msg = handler.obtainMessage();
    msg.what = 3;
    msg.obj = img;
    handler.sendMessage(msg);
}catch (IOException e){
    e.printStackTrace();
}

第六步:通过资源路径下载图片

//获取图片资源路径
String imgUrl = (String) msg.obj;
Glide.with(MainActivity.this)
        .load(imgUrl)
        .into(ivImg);

六、百度地图

简单使用

申请密钥

地址

http://lbsyun.baidu.com/apiconsole/key

创建应用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oenWermz-1610011416475)(Android综合应用.assets/image-20201105090519752.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gesSdDcW-1610011416476)(Android综合应用.assets/image-20201105090551192.png)]

获取SHA1

  • 进去C:\Users\PengHuAnZhi.android

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vYPaE820-1610011416476)(Android综合应用.assets/image-20201105090749817.png)]

  • 输入
keytool -v -list -keystore debug.keystore

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bfT6axxo-1610011416477)(Android综合应用.assets/image-20201105090821101.png)]

  • 密码android

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1rxpLkVc-1610011416478)(Android综合应用.assets/image-20201105090859869.png)]

输入SHA1和包名

30:13:80:F5:23:29:BB:FA:A3:44:89:28:F1:48:61:CF:18:AC:D8:53

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sc5lwUN3-1610011416478)(Android综合应用.assets/image-20201105091027203.png)]

提交,得到AK

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E9OgBwMb-1610011416479)(Android综合应用.assets/image-20201105091134112.png)]

配置环境

将SDK开发库文件进行解压缩得到:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JUUmRgIT-1610011416480)(Android综合应用.assets/image-20201105091305759.png)]

全部引入工程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PCgd8RMw-1610011416480)(Android综合应用.assets/image-20201105091359256.png)]

配置gradle

sourceSets {
    main {
        jniLibs.srcDirs = ['libs']
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-go8xmjxw-1610011416481)(Android综合应用.assets/image-20201105091551449.png)]

同步后:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C0J5HbKJ-1610011416482)(Android综合应用.assets/image-20201105091626839.png)]

配置AK

<meta-data
    android:name="com.baidu.lbsapi.API_KEY"
    android:value="79FANr89amki22Uc4i7oxqD69hjkkLx2" />

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-khcl837F-1610011416482)(Android综合应用.assets/image-20201105091726574.png)]

添加所需权限

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

简单使用

在布局中添加控件

<com.baidu.mapapi.map.MapView
    android:id="@+id/mvMap"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

在应用程序创建时初始化 SDK引用的Context 全局变量,创建地图Activity

// 在使用SDK各组件之前初始化context信息,传入ApplicationContext
// 注意该方法要再setContentView方法之前实现
SDKInitializer.initialize(getApplicationContext());

重新生命周期方法,管理地图生命周期

@Override
protected void onDestroy() {
    super.onDestroy();
    // 在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理
    mMapView.onDestroy();
}

@Override
protected void onResume() {
    super.onResume();
    // 在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理
    mMapView.onResume();
}

@Override
protected void onPause() {
    super.onPause();
    // 在activity执行onPause时执行mMapView. onPause (),实现地图生命周期管理
    mMapView.onPause();
}

基础地图

获取地图控件

MapView mvMap = findViewById(R.id.mvMap);

获取地图控制器

BaiduMap baiduMap = mvMap.getMap();

获取地图UI控制器

UiSettings uiSettings = baiduMap.getUiSettings();

地图类型

//显示普通地图(默认地图形式)
baiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
//显示卫星地图
baiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);
//空白地图
baiduMap.setMapType(BaiduMap.MAP_TYPE_NONE);

实时交通图

//显示交通图(默认不显示交通图)
baiduMap.setTrafficEnabled(true);

热力图

//显示热力图(默认不显示热力图)
baiduMap.setBaiduHeatMapEnabled(true);

地图控制

logo

  • 设置logo位置
mvMap.setLogoPosition(LogoPosition.logoPostionCenterBottom);

position - 枚举类LogoPosition

​ logoPostionCenterBottom 屏幕中下位置

​ logoPostionCenterTop 屏幕中上位置

​ logoPostionleftBottom 屏幕左下位置

​ logoPostionleftTop 屏幕左上位置

​ logoPostionRightBottom 屏幕右下位置

​ logoPostionRightTop 屏幕右上位置

  • 删除logo
//获取地图上方id为1的View(Logo的位置id=1)
//mpView.removeViewAt(1)  霸王删除  不仅仅能删logo,再删则删放大 缩小图标,再删则删比例尺图标
View logo = mvMap.getChildAt(1);
//隐藏Logo的View
if (null != logo && logo instanceof ImageView) {
    logo.setVisibility(View.INVISIBLE);
}

指南针

  • 是否显示
Log.i("phz", "默认指南针显示状态:" +uiSettings.isCompassEnabled());
  • 设置显示
//设置显示指南针
baiduMap.setCompassEnable(true);
uiSettings.setCompassEnabled(true);
//设置指南针位置
baiduMap.setCompassPosition(new Point(800,700));
//设置指南针图标
baiduMap.setCompassIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.znz));

比例尺

  • 是否显示(默认显示)
mvMap.showZoomControls(true);
  • 获取比例尺大小
mvMap.getMapLevel()
  • 通过设置地图更新来重新设置比例尺位置
baiduMap.setOnMapLoadedCallback(new BaiduMap.OnMapLoadedCallback() {
    @Override
    public void onMapLoaded() {
        //改变比例尺和放大缩小图标位置
        //设置放大缩小按钮位置
        mvMap.setZoomControlsPosition(new Point(800, 200));
        //设置比例尺位置
        mvMap.setScaleControlPosition(new Point(200, 300));
    }
});
  • 设置比例尺放大缩小范围

max - [3-21] 且 max > min, 否则无效

min - [3-21] 且 max > min, 否则无效

百度地图的缩放级别从3~21,共19个级别,如下:

5m,10m, 20m, 50m, 100m, 200m, 500m, 1km, 2km, 5km, 10km, 20km, 25km, 50km, 100km, 200km, 500km, 1000km, 2000km。

缩放级别对应为21、20、19、18、17、16、15、14、13、12、11、10、9、8、7、6、5、4、3。

baiduMap.setMaxAndMinZoomLevel(18, 9);
//获取当前允许的最大的比例尺
float max = baiduMap.getMaxZoomLevel();
//获取当前允许的最小的比例尺
float min = baiduMap.getMinZoomLevel();
  • 设置当前地图的缩放级别(默认比例尺大小)
//1. 创建一个地图状态更新对象
MapStatusUpdate statusUpdate = MapStatusUpdateFactory.zoomTo(18);
//2. 通过百度地图控制器应用状态更新
baiduMap.setMapStatus(statusUpdate);

俯视图效果

//创建俯视图的MapStatus对象
MapStatus mapStatus = new MapStatus.Builder()
        .overlook(-45)//俯视范围:(-45,0)
        .build();
//1 创建俯视图的MapStatusUpdate对象
MapStatusUpdate statusUpdate =
        MapStatusUpdateFactory.newMapStatus(mapStatus);
//2 通过百度控制器应用地图状态更新
baiduMap.setMapStatus(statusUpdate);

地图覆盖物

所有叠加或覆盖到地图的内容,我们统称为地图覆盖物。如文本、标注、几何图形 、信息窗口等。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ABFPPDKT-1610011416483)(Android综合应用.assets/image-20201105095846419.png)]

单一标注覆盖物

第一步:创建标注覆盖物对象,并设置其参数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6Yjdbuf4-1610011416484)(Android综合应用.assets/image-20201105100230363.png)]

//获取图标(BitmapDescriptor对象)
BitmapDescriptor bDescriptor = BitmapDescriptorFactory
        .fromResource(R.mipmap.red_marker);
//创建覆盖物显示位置的坐标对象
//116.404017,39.915122
LatLng position = new LatLng(39.915122, 116.404017);
//如果覆盖物包含额外信息,需通过Bundle封装额外信息
Bundle bundle = new Bundle();
bundle.putString("info", "首都北京欢迎您");
MarkerOptions markerOptions = new MarkerOptions()
        .icon(bDescriptor)//必须项,设置覆盖物图标
        .position(position)//必须项,设置覆盖物位置
        .draggable(true)// 可选项,设置是否允许拖拽
        .alpha(0.8f)//可选项,设置透明度
        .rotate(-45)//可选项,设置旋转角度
        .extraInfo(bundle);//可选项,用于封装额外信息

第二步:在地图上显示覆盖物对象

Marker marker = (Marker) baiduMap.addOverlay(markerOptions);

获取额外信息

//通过marker对象获取额外的信息
Bundle extraInfo = marker.getExtraInfo();
Log.i("phz", extraInfo.getString("info"));

添加标注覆盖物集合

第一步:定义标注覆盖物集合对象

List<OverlayOptions> markerOptionsList = new ArrayList<>();

第二步:创建标注覆盖物对象,并添加到集合中

Bundle bundle1 = new Bundle();
bundle1.putString("info", "info1");
OverlayOptions options1 = new MarkerOptions()
        .icon(BitmapDescriptorFactory.fromResource(R.mipmap.green_marker))
        .position(new LatLng(39.625, 117.834))
        .draggable(true)
        .extraInfo(bundle1);
markerOptionsList.add(options1);

Bundle bundle2 = new Bundle();
bundle2.putString("info", "info2");
OverlayOptions options2 = new MarkerOptions()
        .icon(BitmapDescriptorFactory.fromResource(R.mipmap.blue_marker))
        .position(new LatLng(38.925, 116.034))
        .draggable(true)
        .extraInfo(bundle2);
markerOptionsList.add(options2);

第三步:显示覆盖物集合

baiduMap.addOverlays(markerOptionsList);

标注覆盖物

将上面两种覆盖物显示

//显示一个单一的标注覆盖物
showSingleMarkerOption();
//显示标注覆盖物集合
showListMarkerOption();

给百度地图控制器注册标注覆盖物事件

// 注册标注覆盖物点击事件监听器
baiduMap.setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() {
    @Override
    public boolean onMarkerClick(Marker marker) {
        //获取当前的info信息
        Bundle bundle = marker.getExtraInfo();
        String msg = bundle.getString("info");
        Toast.makeText(
                getApplicationContext(),
                msg,
                Toast.LENGTH_SHORT
        ).show();
        return true;
    }
});
//注册标注覆盖物拖拽事件监听器
baiduMap.setOnMarkerDragListener(new BaiduMap.OnMarkerDragListener() {
    @Override
    public void onMarkerDrag(Marker marker) {
        //正在拖拽时触发
    }

    @Override
    public void onMarkerDragEnd(Marker marker) {
        //拖拽结束后触发
        //获取拖拽结束后的位置的坐标对象
        LatLng position = marker.getPosition();
        Log.i("phz", "当前坐标:" + position.toString());
        //获取经度和纬度值
        double lat = position.latitude;//获取纬度
        double lng = position.longitude;//获取经度
        Toast.makeText(
                getApplicationContext(),
                lat + ":" + lng,//经纬度坐标字符串
                Toast.LENGTH_SHORT
        ).show();

    }

    @Override
    public void onMarkerDragStart(Marker marker) {
        //开始拖拽前触发
    }
});

点覆盖物

第一步:创建覆盖物显示位置的坐标对象(点的中心坐标)

LatLng position = new LatLng(39.915129, 116.405558);

第二步:创建覆盖物选项对象,并设置相关参数

DotOptions dotOptions = new DotOptions()
    .center(position)//点的中心坐标
    .color(0xaa0000ff)//点的颜色
    .radius(100)//点的半径
    .zIndex(5);//在Z轴方向上的位置

第三步:在地图上显示覆盖物

Dot dot = (Dot) baiduMap.addOverlay(dotOptions);
dot.setRadius(150);

多边形覆盖物

第一步:显示多边形覆盖物

List<LatLng> points = new ArrayList<>();

第二步:向集合中添加定点

points.add(new LatLng(30.975, 116.212));
points.add(new LatLng(39.527, 116.725));
points.add(new LatLng(39.625, 116.825));
points.add(new LatLng(40.012, 116.935));

第三步:创建多边形覆盖物选项对象

PolygonOptions polygonOptions = new PolygonOptions()
        .points(points)//设置多边形的各个定点坐标
        .fillColor(0xff00ff00)//填充颜色
        .zIndex(3);

第四步:显示

baiduMap.addOverlay(polygonOptions);

几何图形覆盖物

//显示点覆盖物
showDotOptions();
//显示多边形覆盖物
showPolygonOptions();

文字覆盖物

设置文字坐标

LatLng position = new LatLng(39.914082, 116.407913);

创建文字覆盖物选项对象

TextOptions textOptions = new TextOptions()
        .position(position)//文本位置坐标
        .text("*东")//文本
        .fontColor(0xffaa2233)//文本颜色
        .bgColor(0x33333333)//背景色
        .fontSize(50)//文本大小
        .rotate(180)//文本旋转角度
        .typeface(Typeface.DEFAULT_BOLD);

显示

baiduMap.addOverlay(textOptions);

图层覆盖物

第一步:获取图像的BitmapDescriptor对象

BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromResource(R.mipmap.ly);

第二步:创建用于显示覆盖物位置的LatLngBounds对象

LatLngBounds latLngBounds = new LatLngBounds.Builder()
        .include(new LatLng(39.919829, 116.399261))//西南方坐标
        .include(new LatLng(39.929125, 116.407166))//东北方坐标
        .build();

第三步:创建图层覆盖物选项对象

GroundOverlayOptions groundOverlayOptions =
        new GroundOverlayOptions()
                .image(bitmapDescriptor)//覆盖物图像
                .transparency(0.4f)//透明度
                .positionFromBounds(latLngBounds)//显示位置
                .zIndex(2);

第四步:显示

baiduMap.addOverlay(groundOverlayOptions);

简单形式的弹出窗覆盖物

第一步:创建弹出窗覆盖物显示的View对象

Button btn = new Button(getApplicationContext());
btn.setText("简单的弹出窗覆盖物");
btn.setTextSize(50);
btn.setTextColor(Color.DKGRAY);
btn.setBackgroundResource(R.mipmap.national_flag);

第二步:创建弹出窗覆盖物显示的经纬度坐标对象

LatLng position = new LatLng(
        39.909179,
        116.368337
);

第三步:创建弹出窗覆盖物对象

infoWindow1 = new InfoWindow(
        btn,
        position,
        0
);

第四步:显示

baiduMap.showInfoWindow(infoWindow1);

复杂布局的弹出窗覆盖物

第一步:弹出窗覆盖物View对象

View view = LayoutInflater.from(getApplicationContext())
        .inflate(R.layout.infowindow_layout,
                null);

第二步:获取View的BitmapDescriptor对象

BitmapDescriptor bp = BitmapDescriptorFactory.fromView(view);

第三步:创建弹出窗覆盖物显示的经纬度坐标对象

LatLng position = new LatLng(
        39.909179,
        116.434164
);

第四步:创建Infowindow的点击事件监听器

InfoWindow.OnInfoWindowClickListener listener =
        new InfoWindow.OnInfoWindowClickListener() {

            @Override
            public void onInfoWindowClick() {
                //隐藏InfoWinwdow对象
                baiduMap.hideInfoWindow();
            }
        };

第五步:创建InfoWindow对象

infoWindow2 = new InfoWindow(
        bp,
        position,
        0,
        listener
);

第六步:显示

baiduMap.showInfoWindow(infoWindow2);

定位

环境配置

导入库文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rKEPznF0-1610011416484)(Android综合应用.assets/image-20201105102329005.png)]

添加定位service

<service
    android:name="com.baidu.location.f"
    android:enabled="true"
    android:process=":remote">
    <intent-filter>
        <action android:name="com.baidu.location.service_v5.0.0" />
    </intent-filter>
</service>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-osqyKTGj-1610011416485)(Android综合应用.assets/image-20201105102413656.png)]

添加权限

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 这个权限用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!-- 这个权限用于访问GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!-- 获取运营商信息,用于支持提供运营商信息相关的接口-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!-- 用于读取手机当前的状态-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

使用步骤

工具类

package com.example.ch6baidumapdemo;

import com.baidu.location.BDLocation;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.utils.CoordinateConverter;

public class GlobalTool {
    /**
     * 将百度坐标转换成GPS坐标工具类
     *
     * @author fuys
     */
    public final static double a = 6378245.0;
    public final static double ee = 0.00669342162296594323;

    // 判断坐标是否在中国
    public static boolean outOfChina(BDLocation bdLocation) {
        double lat = bdLocation.getLatitude();
        double lon = bdLocation.getLongitude();
        if (lon < 72.004 || lon > 137.8347)
            return true;
        if (lat < 0.8293 || lat > 55.8271)
            return true;
        if ((119.962 < lon && lon < 121.750) && (21.586 < lat && lat < 25.463))
            return true;

        return false;
    }

    public final static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;

    public static BDLocation BAIDU_to_WGS84(BDLocation bdLocation) {
        if (outOfChina(bdLocation)) {
            return bdLocation;
        }
        double x = bdLocation.getLongitude() - 0.0065;
        double y = bdLocation.getLatitude() - 0.006;
        double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
        double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
        bdLocation.setLongitude(z * Math.cos(theta));
        bdLocation.setLatitude(z * Math.sin(theta));3
        return GCJ02_to_WGS84(bdLocation);
    }

    public static BDLocation GCJ02_to_WGS84(BDLocation bdLocation) {
        if (outOfChina(bdLocation)) {
            return bdLocation;
        }
        BDLocation tmpLocation = new BDLocation();
        tmpLocation.setLatitude(bdLocation.getLatitude());
        tmpLocation.setLongitude(bdLocation.getLongitude());
        BDLocation tmpLatLng = WGS84_to_GCJ02(tmpLocation);
        double tmpLat = 2 * bdLocation.getLatitude() - tmpLatLng.getLatitude();
        double tmpLng = 2 * bdLocation.getLongitude()
                - tmpLatLng.getLongitude();
        for (int i = 0; i < 0; ++i) {
            tmpLocation.setLatitude(bdLocation.getLatitude());
            tmpLocation.setLongitude(bdLocation.getLongitude());
            tmpLatLng = WGS84_to_GCJ02(tmpLocation);
            tmpLat = 2 * tmpLat - tmpLatLng.getLatitude();
            tmpLng = 2 * tmpLng - tmpLatLng.getLongitude();
        }
        bdLocation.setLatitude(tmpLat);
        bdLocation.setLongitude(tmpLng);
        return bdLocation;
    }

    public static BDLocation WGS84_to_GCJ02(BDLocation bdLocation) {
        if (outOfChina(bdLocation)) {
            return bdLocation;
        }
        double dLat = transformLat(bdLocation.getLongitude() - 105.0,
                bdLocation.getLatitude() - 35.0);
        double dLon = transformLon(bdLocation.getLongitude() - 105.0,
                bdLocation.getLatitude() - 35.0);
        double radLat = bdLocation.getLatitude() / 180.0 * Math.PI;
        double magic = Math.sin(radLat);
        magic = 1 - ee * magic * magic;
        double sqrtMagic = Math.sqrt(magic);
        dLat = (dLat * 180.0)
                / ((a * (1 - ee)) / (magic * sqrtMagic) * Math.PI);
        dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * Math.PI);
        bdLocation.setLatitude(bdLocation.getLatitude() + dLat);
        bdLocation.setLongitude(bdLocation.getLongitude() + dLon);
        return bdLocation;
    }

    public static double transformLat(double x, double y) {
        double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y
                + 0.2 * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x
                * Math.PI)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(y * Math.PI) + 40.0 * Math.sin(y / 3.0
                * Math.PI)) * 2.0 / 3.0;
        ret += (160.0 * Math.sin(y / 12.0 * Math.PI) + 320 * Math.sin(y
                * Math.PI / 30.0)) * 2.0 / 3.0;
        return ret;
    }

    public static double transformLon(double x, double y) {
        double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1
                * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x
                * Math.PI)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(x * Math.PI) + 40.0 * Math.sin(x / 3.0
                * Math.PI)) * 2.0 / 3.0;
        ret += (150.0 * Math.sin(x / 12.0 * Math.PI) + 300.0 * Math.sin(x
                / 30.0 * Math.PI)) * 2.0 / 3.0;
        return ret;
    }

    /**
     * 百度api里面把GPS坐标转换成百度坐标
     */
    public static LatLng transGpsToBaiduLatLng(LatLng desLatLng1){
        //GPS转百度
        // 将GPS设备采集的原始GPS坐标转换成百度坐标
        CoordinateConverter converter = new CoordinateConverter();
        converter.from(CoordinateConverter.CoordType.GPS);
        // sourceLatLng待转换坐标
        converter.coord(desLatLng1);
        LatLng desLatLng = converter.convert();
        double la = desLatLng.latitude;
        double ln = desLatLng.longitude;
        LatLng ll = new LatLng(la, ln);
        return ll;
    }
}

第一步:获取BaiduMap

MapView mpView = findViewById(R.id.mvMap);
BaiduMap baiduMap = mpView.getMap();

第二步:获取定位客户端类的对象

locClient = new LocationClient(getApplicationContext());

第三步:获取得客户端选项类的对象

LocationClient locOption = new LocationClientOption();

第四步:设置定位参数

//打开GPS
locOption.setOpenGps(true);
//设置扫描间隔时间
locOption.setScanSpan(1000);
//设置定位模式(高精度定位模式)
locOption.setLocationMode(
        LocationClientOption.LocationMode.Hight_Accuracy);
//设置坐标系
locOption.setCoorType("wgs84");
//设置是否需要地址信息
locOption.setIsNeedAddress(true);

第五步:将设置的定位参数应用给定位客户端

locClient.setLocOption(locOption);

第六步:启动定位

locClient.start();
//开启图层定位
baiduMap.setMyLocationEnabled(true);

第七步:注册定位监听器,为了将得的数据显示在地图上

locClient.registerLocationListener(
        new BDAbstractLocationListener() {
    @Override
    public void onReceiveLocation(BDLocation bdLocation) {
        //获取纬度信息
        double lat = bdLocation.getLatitude();
        //获取经度信息
        double lng = bdLocation.getLongitude();
        LatLng position = new LatLng(
                lat,
                lng
        );
        //获取当前定位时间
        String locTime = bdLocation.getTime();
        Log.i("lww", locTime);
        //转换成百度坐标
        LatLng baiduLatLng = GlobalTool.transGpsToBaiduLatLng(position);
        //在地图上显示当前位置
        showLocPostionOnMap(baiduLatLng);
    }
});
/**
 * 将定位的坐标显示在地图上
 * @param baiduLatLng
 */
private void showLocPostionOnMap(LatLng baiduLatLng) {
    //1. 设置坐标显示的图标信息
    MyLocationConfiguration config =
            new MyLocationConfiguration(
                    MyLocationConfiguration.LocationMode.COMPASS,//显示位置罗盘态
                    true,//是否允许显示方向信息
                    BitmapDescriptorFactory.fromResource(R.mipmap.blue_marker)
            );
    //2. 设置显示的样式
    baiduMap.setMyLocationConfiguration(config);
    //设置定位数据
    MyLocationData locData = new MyLocationData.Builder()
            .latitude(baiduLatLng.latitude)
            .longitude(baiduLatLng.longitude)
            .build();
    //设置定位位置
    baiduMap.setMyLocationData(locData);
    //3. 把地图移动到定位位置
    //创建MapStatusUpdate对象
    MapStatusUpdate statusUpdate =
            MapStatusUpdateFactory.newLatLng(baiduLatLng);
    //给地图应用当前状态更新
    baiduMap.animateMapStatus(statusUpdate);
}
上一篇:gson转换对象对字段别名处理@SerializedName注解demo


下一篇:安卓SDK三方库与应用三方库版本冲突的解决方案。