我编写了一个 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; 我
再次感谢您的帮助