Android定位与相册

 

使用Android 原生定位 ,并使用GEO进行城市定位

在Android开发中经常涉及到定位用户位置,以及获得当前设备的城市信息,其实Google已经给出了一套较好的解决方案,我们可以使用Android中的原生定位来完成这项任务,不需要像高德或者百度SDK一样配置繁琐的key,只需要专注于业务逻辑就行

在进行定位处理前,我们要确定是否向用户申请了定位权限

if (ContextCompat.checkSelfPermission(this,
        Manifest.permission.ACCESS_FINE_LOCATION)
        != PackageManager.PERMISSION_GRANTED) {
    //请求对应权限REQUEST_LOCATION_CODE为自定义
    ActivityCompat.requestPermissions(this,
            new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_CODE);
} else {
    //执行需要权限的操作
    doGetLocation();
}

使用下方的工具类进行定位

package com.phcbest.smartcitydemo.utils;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import androidx.core.app.ActivityCompat;

import com.phcbest.smartcitydemo.base.MyApplication;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
 * 经纬度获取
 *
 * @author peng
 * 创建日期:2020/9/27 14
 * 描述:
 */
public class GLocationUtils {


    private static String locationProvider;

    public interface CallBackLocation {
        /**
         * coolback
         */
        void callBack(Location location);
    }

    public static void getLatAndLog(final CallBackLocation callBackLocation) {
//       不支持网络定位,需要在空旷的地方定位
        final LocationManager locationManager = (LocationManager) MyApplication.getContext()
                .getSystemService(Context.LOCATION_SERVICE);
        List<String> providers = locationManager.getProviders(true);
        //判断位置类型是什么
        if (providers.contains(LocationManager.GPS_PROVIDER)) {
            locationProvider = LocationManager.GPS_PROVIDER;
        } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
            locationProvider = LocationManager.NETWORK_PROVIDER;
        } else {
            Toast.makeText(MyApplication.getContext(), "没有可用的位置提供器",
                    Toast.LENGTH_SHORT).show();
        }
        //获取位置
        if (ActivityCompat.checkSelfPermission(
                MyApplication.getContext(), Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(MyApplication.getContext(),
                Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(MyApplication.getContext(), "您缺少权限",
                    Toast.LENGTH_SHORT).show();
            return;
        }


        locationManager.requestLocationUpdates(locationProvider,
                3000,
                0,
                new LocationListener() {
                    @Override
                    public void onLocationChanged(Location location) {
                        //解析地理位置
                        //拿到了第一次位置后就直接关掉
                        locationManager.removeUpdates(this);
                        Log.i("location", "backLocation: " + location.toString());
                        //回调返回location对象
                        callBackLocation.callBack(location);
                    }


                    @Override
                    public void onStatusChanged(String provider, int status, Bundle extras) {

                    }

                    @Override
                    public void onProviderEnabled(String provider) {

                    }

                    @Override
                    public void onProviderDisabled(String provider) {
                    }
                });
    }

    //获取地址信息:城市、街道等信息
    public static List<Address> getAddress(Location location) {
        try {
            if (location != null) {
                Geocoder gc = new Geocoder(MyApplication.getContext(), Locale.getDefault());
                List<Address> result = gc.getFromLocation(location.getLatitude(),
                        location.getLongitude(), 5);
                Toast.makeText(MyApplication.getContext(),
                        "获取地址信息:" + result.toString(), Toast.LENGTH_LONG).show();
                Log.v("TAG", "获取地址信息:" + result.toString());
                return result;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ArrayList<>();
    }
}

调用相册获取图片,并转换为位图对象或byte集合

请求权限

//申请文件权限
if (ContextCompat.checkSelfPermission(UpSetActivity.this,
        Manifest.permission.WRITE_EXTERNAL_STORAGE)
        != PackageManager.PERMISSION_GRANTED) {
    //请求对应权限
    ActivityCompat.requestPermissions(UpSetActivity.this,
            new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_CODE);
} else {
    //执行需要权限的操作
    doSelectPhoto();
}

权限请求回调

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_WRITE_CODE) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            doSelectPhoto();
        }
    }
}

跳转拍照的intent

private void doSelectPhoto() {
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.setType("image/*");
    startActivityForResult(intent, 1);
}

打开图片选择界面的回调

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 1) {
        //对uri进行操作
        Uri uri = data.getData();
        //获得内容解析器
        ContentResolver contentResolver = MyApplication.getContext().getContentResolver();
        //获得fd文件描述符
        try {
            ParcelFileDescriptor pfd = contentResolver.openFileDescriptor(uri, "r");
            FileDescriptor fileDescriptor = pfd.getFileDescriptor();
            //使用位图工厂将fd变为位图
            Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
            mIvImage.setImageBitmap(bitmap);
            //将文件转换为byte数组
            FileInputStream fileInputStream = new FileInputStream(fileDescriptor);
            bytes = new byte[fileInputStream.available()];
            int read = fileInputStream.read(bytes);
            Log.i(TAG, "onActivityResult: " + read);

            pfd.close();
            fileInputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

将图片上传到服务器

  • retrofit接口

    @Multipart
    @POST("/work/covererror/postFile/{euid}")
    Observable<Map<String, String>> putFile(@Path("euid") String euid, @Part MultipartBody.Part file);
    
  • 使用接口

    RequestBody requestBody = RequestBody.create(MediaType.parse("image/*"), imageByte);
    MultipartBody.Part part = MultipartBody.Part.createFormData("file", uri2file(fileUri), requestBody);
    Observable<Map<String, String>> mapObservable = apiCoverError.putFile(recordsBean.getUid(), part);
    mapObservable.observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .subscribe(new Observer<Map<String, String>>() {
                @Override
                public void onSubscribe(@NonNull Disposable d) {
      
                }
      
                @Override
                public void onNext(@NonNull Map<String, String> stringStringMap) {
                    Toast.makeText(getContext(), "上传成功", Toast.LENGTH_SHORT).show();
                }
      
                @Override
                public void onError(@NonNull Throwable e) {
                    Toast.makeText(getContext(), "上传失败", Toast.LENGTH_SHORT).show();
                }
      
                @Override
                public void onComplete() {
      
                }
            });
    

    ` uri2file`方法是用于使用uri获得文件的名字

    private String uri2file(Uri uri) {
        String image_path;
        Cursor cursor = getContext().getContentResolver().query(uri, null, null, null, null);
        if (cursor == null) {
            image_path = uri.getPath();
        } else {
            int columnIndexOrThrow = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
            cursor.moveToFirst();
            image_path = cursor.getString(columnIndexOrThrow);
        }
        Log.i(TAG, "uri2file: " + image_path);
        return image_path;
    }
    

    imageByte是将获得的文件转换为的byte数组