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

时间:2021-11-26 15:18:30

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

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


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


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

Android使用百度地图定位并显示手机位置后使用前置摄像头“偷拍”如图,jar包文件最好与so文件版本一致

 package com.agile.androiddgs.activity;

 import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window; import com.agile.androiddgs.R;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.search.core.SearchResult;
import com.baidu.mapapi.search.geocode.GeoCodeResult;
import com.baidu.mapapi.search.geocode.GeoCoder;
import com.baidu.mapapi.search.geocode.OnGetGeoCoderResultListener;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeOption;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List; public class PositionActivity extends Activity implements OnGetGeoCoderResultListener{
/**********************百度地图定位以及地图功能*********************************/
private String permissionInfo;
private final int SDK_PERMISSION_REQUEST = 127;
private MapView mapView = null;
private BaiduMap baiduMap = null; // 定位相关声明
private LocationClient locationClient = null;
//自定义图标
private BitmapDescriptor mCurrentMarker = null;
private boolean isFirstLoc = true;// 是否首次定位 GeoCoder mSearch = null; // 搜索模块,也可去掉地图模块独立使用 private BDLocationListener myListener = new BDLocationListener() {
@Override
public void onReceiveLocation(BDLocation location) {//定位成功
// map view 销毁后不在处理新接收的位置
if (location == null || mapView == null)
return;
try {
mSearch.reverseGeoCode(new ReverseGeoCodeOption().location(new LatLng(location.getLatitude(), location.getLongitude()))); }catch (Exception e){
e.printStackTrace();
} MyLocationData locData = new MyLocationData.Builder()
.accuracy(location.getRadius())
// 此处设置开发者获取到的方向信息,顺时针0-360
.direction(100).latitude(location.getLatitude())
.longitude(location.getLongitude()).build();
baiduMap.setMyLocationData(locData); //设置定位数据 if (isFirstLoc) {//第一次定位
isFirstLoc = false; LatLng ll = new LatLng(location.getLatitude(),
location.getLongitude());
MapStatusUpdate u = MapStatusUpdateFactory.newLatLngZoom(ll, 16); //设置地图中心点以及缩放级别
// MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(ll);
baiduMap.animateMapStatus(u);
}
}
}; /**********************************摄像头***********************************************/
private SurfaceView mySurfaceView;
private SurfaceHolder myHolder;
private Camera myCamera;
int mCurrentCamIndex = 0; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// after andrioid m,must request Permiision on runtime
getPersimmions();
requestWindowFeature(Window.FEATURE_NO_TITLE);
// 在使用SDK各组件之前初始化context信息,传入ApplicationContext
// 注意该方法要再setContentView方法之前实现
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.activity_position); // 初始化搜索模块,注册事件监听
mSearch = GeoCoder.newInstance(); mapView = (MapView) this.findViewById(R.id.mapView); // 获取地图控件引用
baiduMap = mapView.getMap();
//开启定位图层
baiduMap.setMyLocationEnabled(true); locationClient = new LocationClient(getApplicationContext()); // 实例化LocationClient类
locationClient.registerLocationListener(myListener); // 注册监听函数
this.setLocationOption(); //设置定位参数
locationClient.start(); // 开始定位
// baiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL); // 设置为一般地图 // baiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE); //设置为卫星地图
// baiduMap.setTrafficEnabled(true); //开启交通图 } @TargetApi(23)
private void getPersimmions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ArrayList<String> permissions = new ArrayList<String>();
/***
* 定位权限为必须权限,用户如果禁止,则每次进入都会申请
*/
// 定位精确位置
if(checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){
permissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
if(checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){
permissions.add(Manifest.permission.ACCESS_COARSE_LOCATION);
}
/*
* 读写权限和电话状态权限非必要权限(建议授予)只会申请一次,用户同意或者禁止,只会弹一次
*/
// 读写权限
if (addPermission(permissions, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
permissionInfo += "Manifest.permission.WRITE_EXTERNAL_STORAGE Deny \n";
}
// 读取电话状态权限
if (addPermission(permissions, Manifest.permission.READ_PHONE_STATE)) {
permissionInfo += "Manifest.permission.READ_PHONE_STATE Deny \n";
} if (permissions.size() > 0) {
requestPermissions(permissions.toArray(new String[permissions.size()]), SDK_PERMISSION_REQUEST);
}
}
} @TargetApi(23)
private boolean addPermission(ArrayList<String> permissionsList, String permission) {
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { // 如果应用没有获得对应权限,则添加到列表中,准备批量申请
if (shouldShowRequestPermissionRationale(permission)){
return true;
}else{
permissionsList.add(permission);
return false;
} }else{
return true;
}
} @TargetApi(23)
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
// TODO Auto-generated method stub
super.onRequestPermissionsResult(requestCode, permissions, grantResults); } // 三个状态实现地图生命周期管理
@Override
protected void onDestroy() {
//退出时销毁定位
locationClient.stop();
baiduMap.setMyLocationEnabled(false);
// TODO Auto-generated method stub
super.onDestroy();
mapView.onDestroy();
mapView = null;
} @Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
mapView.onResume();
} @Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
mapView.onPause();
} /**
* 设置定位参数
*/
private void setLocationOption() {
LocationClientOption option = new LocationClientOption();
option.setOpenGps(true); // 打开GPS
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);// 设置定位模式
option.setCoorType("bd09ll"); // 返回的定位结果是百度经纬度,默认值gcj02
option.setScanSpan(5000); // 设置发起定位请求的间隔时间为5000ms
option.setIsNeedAddress(true); // 返回的定位结果包含地址信息
option.setNeedDeviceDirect(true); // 返回的定位结果包含手机机头的方向 locationClient.setLocOption(option);
} @Override
public void onGetGeoCodeResult(GeoCodeResult geoCodeResult) { }
/**
根据经纬度反编为具体地址
*/
@Override
public void onGetReverseGeoCodeResult(ReverseGeoCodeResult reverseGeoCodeResult) {
if (reverseGeoCodeResult == null || reverseGeoCodeResult.error != SearchResult.ERRORNO.NO_ERROR)
{
return;
} String address = reverseGeoCodeResult.getAddress();
} }

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

 //初始化surfaceview
new Thread(new Runnable() {
@Override
public void run() { mySurfaceView = (SurfaceView) findViewById(R.id.camera_surfaceview); //初始化surfaceholder
myHolder = mySurfaceView.getHolder();
myHolder.addCallback(new SurfaceViewCallback());
myHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); }
}).start();

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

 /***************************************************************************************/
private final class SurfaceViewCallback implements android.view.SurfaceHolder.Callback {
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3)
{ try {
myCamera.setPreviewDisplay(arg0);
myCamera.startPreview();
setCameraDisplayOrientation(PositionActivity.this, mCurrentCamIndex, myCamera);
new Handler().postDelayed(new Runnable(){ public void run() {
              //拍照
myCamera.takePicture(shutterCallback, rawPictureCallback,
jpegPictureCallback);
} }, 5000); } catch (Exception e) {
e.printStackTrace();
}
}
public void surfaceCreated(SurfaceHolder holder) {
// mCamera = Camera.open();
//change to front camera
myCamera = openFrontFacingCameraGingerbread();
// get Camera parameters
Camera.Parameters params = myCamera.getParameters(); List<String> focusModes = params.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
// Autofocus mode is supported
}
} public void surfaceDestroyed(SurfaceHolder holder) {
myCamera.stopPreview();
myCamera.release();
myCamera = null;
}
} //根据横竖屏自动调节preview方向,Starting from API level 14, this method can be called when preview is active.
private static void setCameraDisplayOrientation(Activity activity,int cameraId, Camera camera)
{
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation(); //degrees the angle that the picture will be rotated clockwise. Valid values are 0, 90, 180, and 270.
//The starting position is 0 (landscape).
int degrees = 0;
switch (rotation)
{
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
{
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
}
else
{
// back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
} public void scanFileToPhotoAlbum(String path) { MediaScannerConnection.scanFile(PositionActivity.this,
new String[] { path }, null,
new MediaScannerConnection.OnScanCompletedListener() { public void onScanCompleted(String path, Uri uri) {
Log.i("TAG", "Finished scanning " + path);
}
});
} private Camera openFrontFacingCameraGingerbread() {
int cameraCount = 0;
Camera cam = null;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
cameraCount = Camera.getNumberOfCameras(); for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
Camera.getCameraInfo(camIdx, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
try {
cam = Camera.open(camIdx);
mCurrentCamIndex = camIdx;
} catch (RuntimeException e) {
e.printStackTrace();
}
}
} return cam;
} Camera.ShutterCallback shutterCallback = new Camera.ShutterCallback() {
@Override
public void onShutter() {
}
}; Camera.PictureCallback rawPictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] arg0, Camera arg1) { }
}; Camera.PictureCallback jpegPictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); int options = 100;
ByteArrayInputStream isBm = new ByteArrayInputStream(arg0);//把压缩后的数据baos存放到ByteArrayInputStream中
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStr bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中 while ( baos.toByteArray().length / 1024>1) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩
baos.reset();//重置baos即清空baos
bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中
options -= 10;//每次都减少10
} /*String fileName = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
.toString()
+ File.separator
+ "PicTest_" + System.currentTimeMillis() + ".jpg";
File file = new File(fileName);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdir();
} try {
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(file));
bos.write(arg0);
bos.flush();
bos.close();
scanFileToPhotoAlbum(file.getAbsolutePath());
Toast.makeText(PositionActivity.this, "[Test] Photo take and store in" + file.toString(), Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(PositionActivity.this, "Picture Failed" + e.toString(),
Toast.LENGTH_LONG).show();
e.printStackTrace();
}*/
};
};

布局文件如下

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<!-- 添加地图控件 -->
<com.baidu.mapapi.map.MapView
android:id="@+id/mapView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true" />
</LinearLayout> <!-- 预览框,长宽都为0.1 -->
<SurfaceView
android:id="@+id/camera_surfaceview"
android:layout_width="0.1dp"
android:layout_height="0.1dp" >
</SurfaceView>
</LinearLayout>

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

Android使用百度地图定位并显示手机位置后使用前置摄像头“偷拍”的更多相关文章

  1. android中百度地图定位的实现方法(仅适用于真机&plus;WIFI联网环境)

    注意:此代码的环境是:真机(系统版本为Android4.2.2)+WIFI联网(才能实现最后的运行结果):使用虚拟机调试会出现各种问题. 第一步:下载SDK和申请Key 到百度的网站http://de ...

  2. Android使用百度地图定位

    下面事例是使用Android平台的部分代码.对于这个平台百度的开放人员已经写了完整的demo,把工程导入到eclipse中之后一般没有错误,如果报错的话,eclipse也会给出提示.一般可以通过将pr ...

  3. Android利用百度地图定位

    百度地图照着百度的教程做的总是出现报错 请帮我看看错误在那 2013-12-13 15:16168海军 | 分类:百度地图 | 浏览1252次 java.lang.RuntimeException: ...

  4. Android使用百度地图出现闪退及定位时显示蓝屏问题

     目录 1.Android使用百度地图出现闪退 2.Android使用百度地图定位出现蓝屏问题     1.Android使用百度地图出现闪退 一般情况下出现闪退是在AndroidManifest.x ...

  5. Android studio 百度地图开发(2)地图定位

    Android studio 百度地图开发(2)地图定位 email:chentravelling@163.com 开发环境:win7 64位,Android Studio,请注意是Android S ...

  6. Android 百度地图定位&lpar;手动&plus;自动&rpar; 安卓开发教程

    近由于项目需要,研究了下百度地图定位,他们提供的实例基本都是用监听器实现自动定位的.我想实现一种效果:当用户进入UI时,不定位,用户需要定位的时候,自己手动点击按钮,再去定位当前位置.  经过2天研究 ...

  7. Android集成百度地图SDK

    本Demo中所含功能 1:定位,显示当前位置 2:地图多覆盖物(地图描点.弹出该点的具体信息) 3:坐标地址互相换算 4:POI兴趣点检索 5:线路查询(步行,驾车,公交) 6:绘制线路(OpenGL ...

  8. 百度地图定位SDK 之构想

    百度地图定位 前提 从香港旅游回来,心中油然升起一股热血滂湃,激励自己发现市场需求,向创业奋进,朝着梦想前进. 简介 百度Android定位SDK支持Android1.5以及以上设备,提供: 定位功能 ...

  9. Android studio 百度地图开发(3)地图导航

    Android studio 百度地图开发(3)地图导航 email:chentravelling@163.com 开发环境:win7 64位,Android Studio,请注意是Android S ...

随机推荐

  1. MICAPS二次开发一些功能调用

    1.调用地图并将micaps文件加载地图上 IFileBindingService fbs = ServiceLocator.Current.GetInstance< IFileBindingS ...

  2. C&num;泛型代理、泛型接口、泛型类型、泛型方法

    //http://www.cnblogs.com/JeffreySun/archive/2012/11/14/2770211.html //http://www.baqima.com/a/2628.h ...

  3. http的六种请求方法

    1.get: GET可以说是最常见的了,它本质就是发送一个请求来取得服务器上的某一资源.资源通过一组HTTP头和呈现数据(如HTML文本,或者图片或者视频等)返回给客户端.GET请求中,永远不会包含呈 ...

  4. Codeforces &num;259 Div&period;2

    A. Little Pony and Crystal Mine 模拟题. 用矩阵直接构造或者直接根据关系输出 B. Little Pony and Sort by Shift 模拟题. 通过提供的操作 ...

  5. Liferay7 BPM门户开发之30&colon; 通用帮助类Validator、ArrayUtil、StringUtil等使用

    废话不多说,直接上代码. 验证类Validator 主要是空验证.数字.格式验证 调用的例子: protected void validateEmailFrom(ActionRequest actio ...

  6. Qt之QHeaderView自定义排序(QSortFilterProxyModel)

    简述 对以上节的排序,我们衍伸了两点: 把一个字符串前面的数据按照字符串比较,而后面的数据按照整形比较. 将整形显示为字符串,而排序依然正常呢. 为了分别描述,这里我们先解决问题1. 简述 效果 处理 ...

  7. Kali Linux 优化过程

    修改输入法横向候选字 vim ~/.config/fcitx/conf fcitx-classic-ui.config 修改此行 为 false  :VerticalList=False   mb这玩 ...

  8. properties 配置文件如何换行

    在使用properties配置文件的时候我们经常碰到如下两个问题 1:当a=b中的b值内容特别长的时候为了阅读方便我们手动换行,但如果我们直接回车那么后面的数据就会丢失.那如何解决呢? 例如: a=a ...

  9. vue组件利用formdata图片预览以及上传《转载》

    转载修改 在项目中直接新建一个单文件页,复制一下代码即可       upload组件: <template> <div class="vue-uploader" ...

  10. SQL Server 数据库限制单用户使用和解除单用户使用

    一个在单用户(SINGLE_USER)模式下的数据库一次只能有一个连接.在限制用户(RESTRICTED_USER)模式下的数据库只能接受被认为是“合格”用户的连接——这些用户属于dbcreator或 ...