我编写了一个 android 活动来充当简单的相机,但是当我拍摄照片时,活动会存储图像并在旁边存储一个 txt 文件,该文件记录手机的 gps 位置和方向(即加速度计和数字罗盘读数) . 该活动有效,但我不确定它是否正确编写。我是 android 和 java 的新手,所以如果有人可以检查它,那就太好了。我很担心,因为当我第一次开始开发这个时,我的开发设备开始变得有趣和过热等等。虽然我不能 100% 确定,但这可能与编码错误有关。也许与我将所有内容的引用传递给每个类的方式有关,这可能不是一个好主意,但我想不出另一种方法,感谢您的帮助。
这是主要的活动代码:
package com.mobimm;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.ShutterCallback;
import android.os.Bundle;
import android.os.Handler;
import android.text.format.Time;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.ViewGroup.LayoutParams;
public class CameraAct extends Activity {
private CamCapture mPreview;
private DrawOnTop mDrawOnTop;
private OrientationManager mOri;
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Hide the window title.
requestWindowFeature(Window.FEATURE_NO_TITLE);
// Create our Preview view and set it as the content of our activity.
mOri = new OrientationManager();
mPreview = new CamCapture(this, mOri);
mDrawOnTop = new DrawOnTop(this, mPreview, mOri);
setContentView(mPreview);
addContentView(mDrawOnTop, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
mHandler = new Handler();
mHandler.postDelayed(mUpdateUI, 1000);
}
@Override
protected void onResume() {
super.onResume();
if (mOri.isSupported(this.getApplicationContext())) {
mOri.startListening(this.getApplicationContext());
}
mPreview.resume();
}
@Override
protected void onPause() {
super.onPause();
if (mOri.isSupported(this.getApplicationContext())) {
mOri.stopListening();
}
mPreview.pause();
}
private Runnable mUpdateUI = new Runnable() {
public void run() {
mDrawOnTop.invalidate();
mHandler.postDelayed(mUpdateUI, 1000);
}
};
}
// ----------------------------------------------------------------------
class DrawOnTop extends View {
Paint mPaintWhite;
String mStatus;
CamCapture mCam;
OrientationManager mOri;
public DrawOnTop(Context context, CamCapture cam, OrientationManager ori) {
super(context);
mCam = cam;
mOri = ori;
mStatus = "Waiting";
mPaintWhite = new Paint();
mPaintWhite.setStyle(Paint.Style.FILL);
mPaintWhite.setColor(Color.WHITE);
mPaintWhite.setTextSize(25);
}
@Override
protected void onDraw(Canvas canvas) {
int canvasHeight = canvas.getHeight();
// Draw String
canvas.drawText(Math.round(mOri.getAzimuth())+" "+Math.round(mOri.getPitch())+" "+Math.round(mOri.getRoll()), 10, canvasHeight - 30, mPaintWhite);
if (mOri.getGPSAcc() 0) {
canvas.drawText((Math.round((mOri.getLat()*100000))/100000.0)+","+(Math.round((mOri.getLng()*100000))/100000.0)+" "+mOri.getGPSAcc(), 10, canvasHeight - 60, mPaintWhite);
} else {
canvas.drawText("Looking For Satillates "+mOri.getGPSAcc(), 10, canvasHeight - 60, mPaintWhite);
}
canvas.drawText(mStatus, 10, canvasHeight - 90, mPaintWhite);
}
@Override
public boolean onTouchEvent(final MotionEvent event) {
mCam.setRecording(true);
return true;
}
}
// ----------------------------------------------------------------------
class CamCapture extends SurfaceView implements SurfaceHolder.Callback {
SurfaceHolder mHolder;
Camera mCamera;
// byte[] mYUVData;
// int[] mRGBData;
Bitmap mBitmap[];
int mImageWidth, mImageHeight;
long mLastImgScan;
boolean mRecording;
String mFilename;
String mCSVStore;
OrientationManager mOri;
PictureCallback mJpegCallback;
ShutterCallback mShutterCallback;
CamCapture(CameraAct context, OrientationManager ori) {
super((Context) context);
mOri = ori;
mRecording = false;
mCSVStore = "";
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mHolder.setFormat(PixelFormat.TRANSLUCENT);
mImageWidth = 0;
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, acquire the camera and tell it where
// to draw.
mCamera = Camera.open();
try {
mCamera.setPreviewDisplay(holder);
// Preview callback used whenever new viewfinder frame is available
mCamera.setPreviewCallback(new PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera camera)
{
if (mImageWidth == 0)
{
// Initialize the draw-on-top companion
Camera.Parameters params = camera.getParameters();
mImageWidth = params.getPreviewSize().width;
mImageHeight = params.getPreviewSize().height;
// mYUVData = new byte[data.length*10];
// mRGBData = new int[data.length*10];
mLastImgScan = System.currentTimeMillis();
}
if (mRecording) {
mRecording = false;
mBitmap = new Bitmap[1];
mLastImgScan = System.currentTimeMillis();
camera.takePicture(mShutterCallback, null, mJpegCallback);
Log.w("CamInfo", "Taking Photo");
}
}
});
mShutterCallback = new ShutterCallback() {
public void onShutter() {
mCSVStore = mOri.getString();
Log.w("CamInfo", "Getting Cam Data For Photo");
}
};
mJpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] _data, Camera _camera) {
Log.w("CamInfo", "Saving Cam Image For Photo");
try {
FileOutputStream outimg = new FileOutputStream("/sdcard/fypcamera/"+mFilename+".jpg");
outimg.write(_data);
outimg.close();
//mBitmap[mCounter] = BitmapFactory.decodeByteArray(_data, 0, _data.length);
_data = null;
outimg = null;
File f = new File("/sdcard/cameratesting/"+mFilename+".csv");
//File f = new File("/sdcard/"+mFilename+".txt");
FileWriter fw = new FileWriter(f);
BufferedWriter outtxt = new BufferedWriter(fw);
outtxt.write(mCSVStore);
outtxt.close();
f = null;
outtxt = null;
mCSVStore = "";
} catch (Exception e) {
e.printStackTrace();
}
mBitmap = null;
mCSVStore = "";
mCamera.startPreview();
}
};
} catch (IOException exception) {
mCamera.release();
mCamera = null;
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// Surface will be destroyed when we return, so stop the preview.
// Because the CameraDevice object is not a shared resource, it's very
// important to release it when the activity is paused.
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// Now that the size is known, set up the camera parameters and begin
// the preview.
if (mCamera != null) {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(320, 240);
parameters.setPreviewFrameRate(10);
parameters.setSceneMode(Camera.Parameters.SCENE_MODE_LANDSCAPE);
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);
parameters.setJpegQuality(100);
//parameters.setPictureFormat(PixelFormat.RGB_565);
//parameters.setPreviewFormat(PixelFormat.RGB_565); // set preview to ImageFormat.RGB_565
mCamera.setParameters(parameters);
mCamera.startPreview();
}
}
public void pause() {
if (mCamera != null) mCamera.stopPreview();
}
public void resume() {
if (mCamera != null) mCamera.startPreview();
}
public void setRecording(boolean set) {
Time timestr = new Time();
timestr.set(System.currentTimeMillis());
mFilename = timestr.format2445();
mRecording = set;
}
public boolean getRecording() {
return (mRecording || mCSVStore != "");
}
}
这是orientationmanager代码:
包 com.mobimm;
导入 java.util.List;
导入android.content.Context;
导入android.hardware.Sensor;
导入android.hardware.SensorEvent;
导入 android.hardware.SensorEventListener;
导入 android.hardware.SensorManager;
导入android.location.Location;
导入 android.location.LocationListener;
导入 android.location.LocationManager;
导入android.os.Bundle;
公共类 OrientationManager {
私人传感器传感器;
私有传感器管理器传感器管理器;
私人位置管理器位置管理器;
私人双纬度;
私人双液化天然气;
私人浮动 gpsacc;
私人浮动[] mR = null;
私人浮动[] mi = null;
私人浮动[] mMag;
私人浮动[] mGrv;
私人浮动[] mAng;
// 你可以使用 OrientationListener 数组代替
// 如果你打算使用多个监听器
/** 表示是否支持方向传感器 */
支持私有布尔值;
/** 表示方向传感器是否正在运行 */
私人布尔运行=假;
公共方向管理器(){
mMag = 新浮点数[3];
mGrv = 新浮点数[3];
mAng = 新浮点数[3];
mR = 新浮点数[16];
mi = 新浮点数[16];
}
/**
* 如果经理正在监听方向变化,则返回 true
*/
公共布尔 isListening() {
返回运行;
}
/**
* 返回 Ori 矩阵
*/
公共浮动[] getMatrix() {
返回mR;
}
/**
* 返回磁矢量
*/
公共 Vec getMagVec() {
返回新的 Vec(mMag[0], mMag[1], mMag[2]);
}
/**
* 返回重力向量
*/
公共 Vec getGravVec() {
返回新的 Vec(mGrv[0], mGrv[1], mGrv[2]);
}
/**
* 返回方位角
*/
公共浮动 getAzimuth() {
返回 mAng[0];
}
/**
* 返回方位角
*/
公共浮动 getPitch() {
返回 mAng[1];
}
/**
* 返回方位角
*/
公共浮动 getRoll() {
返回 mAng[2];
}
/**
* 返回纬度
*/
公共浮动 getLat() {
返回(浮动)纬度;
}
/**
* 返回 lng
*/
公共浮动getLng(){
返回(浮动)液化天然气;
}
/**
* 返回 lng
*/
公共浮动 getGPSAcc() {
返回(浮动)gpsacc;
}
公共字符串 getString() {
// 输出格式 = time,lat,lng,GPS acc, Ori Azimuth, Ori Pitch, Ori Roll, Acc x, Acc y, Acc z, Mag x, Mag y, Mag z
字符串 rtn = System.currentTimeMillis()+"\n";
rtn +=“全球定位系统”,;
rtn += 纬度+",";
rtn += lng+",";
rtn += gpsacc+"\n";
rtn += "角度";
rtn += mAng[0]+",";
rtn += mAng[1]+",";
rtn += mAng[2]+"\n";
rtn += "重力";
rtn += mGrv[0]+",";
rtn += mGrv[1]+",";
rtn += mGrv[2]+",";
rtn += "磁铁";
rtn += mMag[0]+",";
rtn += mMag[1]+",";
rtn += mMag[2]+"\n";
rtn += "矩阵";
rtn += mR[0]+",";
rtn += mR[1]+",";
rtn += mR[2]+",";
rtn += mR[3]+"\n";
rtn += " ,";
rtn += mR[4]+",";
rtn += mR[5]+",";
rtn += mR[6]+",";
rtn += mR[7]+"\n";
rtn += " ,";
rtn += mR[8]+",";
rtn += mR[9]+",";
rtn += mR[10]+",";
rtn += mR[11]+"\n";
rtn += " ,";
rtn += mR[12]+",";
rtn += mR[13]+",";
rtn += mR[14]+",";
rtn += mR[15]+"\n";
返回rtn;
}
/**
* 注销监听器
*/
公共无效停止监听(){
运行=假;
尝试 {
if (sensorManager != null && sensorEventListener != null) {
sensorManager.unregisterListener(sensorEventListener);
}
if (locationManager != null && locListener != null) {
locationManager.removeUpdates(locListener);
}
} 捕捉(异常 e){}
}
/**
* 如果至少有一个方向传感器可用,则返回 true
*/
公共布尔isSupported(上下文上下文){
如果(支持 == null){
如果(上下文!= null){
sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
//列出传感器 = sensorManager.getSensorList(Sensor.TYPE_ALL);
//sensors = sensorManager.getSensorList(Sensor.TYPE_ORIENTATION);
//支持 = new Boolean(sensors.size() > 0);
列出传感器 = sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
支持 = new Boolean(sensors.size() > 0);
传感器 = sensorManager.getSensorList(Sensor.TYPE_MAGNETIC_FIELD);
支持 = (支持 && new Boolean(sensors.size() > 0));
} 别的 {
支持 = Boolean.FALSE;
}
}
支持退货;
}
/**
* 注册一个监听器并开始监听
*/
public void startListening(上下文上下文){
sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
/*
列出传感器 = sensorManager.getSensorList(
传感器.TYPE_ORIENTATION);
如果(传感器大小()> 0){
传感器 = 传感器.get(0);
运行 = sensorManager.registerListener(
传感器事件监听器,传感器,
SensorManager.SENSOR_DELAY_GAME);
}
*/
列出传感器 = sensorManager.getSensorList(
Sensor.TYPE_ACCELEROMETER);
如果(传感器大小()> 0){
传感器 = 传感器.get(0);
运行 = sensorManager.registerListener(
传感器事件监听器,传感器,
SensorManager.SENSOR_DELAY_GAME);
}
传感器 = sensorManager.getSensorList(
传感器.TYPE_MAGNETIC_FIELD);
如果(传感器大小()> 0){
传感器 = 传感器.get(0);
运行 = sensorManager.registerListener(
传感器事件监听器,传感器,
SensorManager.SENSOR_DELAY_GAME);
}
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
尝试 {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000L, 2f, locListener);
} 捕捉(异常 e){
e.printStackTrace();
}
}
/**
* 从方向监听器监听事件的监听器
*/
私人 SensorEventListener sensorEventListener =
新的 SensorEventListener() {
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
公共无效 onSensorChanged(SensorEvent 事件){
/*
if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
方位角 = event.values[0]; // 方位角
音调 = event.values[1]; // 沥青
滚动 = event.values[2]; // 卷
}
*/
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
mGrv = event.values;
}
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
mMag = event.values;
}
if (SensorManager.getRotationMatrix(mR, mi, mGrv, mMag)) {
SensorManager.getOrientation(mR, mAng);
mAng[0] = (float) Math.toDegrees(mAng[0]);
mAng[1] = (float) Math.toDegrees(mAng[1]);
mAng[2] = (float) Math.toDegrees(mAng[2]);
浮动[] tmp = 新浮动[16];
对于 (int i = 0; 我
再次感谢您的帮助