안드로이드 개발 질문/답변
(글 수 45,052)
공부 겸으로 카메라를 제작하려 그러는데 자꾸 문제가 발생합니다. 카메라 화면에 넘어갈 때 강제종료되는 이 슬픔...
첫번쩨 화면에서 버튼을 누르면 카메라 뷰로 갈 때 바로 튕겨버립니다.
현재 CameraActivity 없이 Preview만을 동작시키면 미리보기는 됩니다. 단, 사진 찍는 것이 안되지요...
LogCat과 코드 올립니다. 스크롤의 압박이 조금 심합니다.. 이해해 주시면 감사하겠습니다.
밑 코드 부분에 setContentView(R.layout.main);를 없애면 에러가 뜨지 않습니다. 단, 카메라프리뷰가 뜨지 않고 onTouch로 사진을 찍으랴 하면 튕깁니
CameraActivity.java
import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.text.DecimalFormat; import java.util.Calendar; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.hardware.Camera; import android.media.AudioManager; import android.media.ToneGenerator; import android.os.Bundle; import android.util.Log; import android.view.Display; import android.view.MotionEvent; import android.view.WindowManager; import android.widget.Toast;
public class CameraActivity extends Activity {
private Preview mPreview;
private byte[][] mImageData;
private boolean gFocussed = false;
private boolean gCameraPressed = false;
private static SharedPreferences sPrefs = null; public static final String KEY_POPUP_ENV = "key_env"; public static final String KEY_POPUP_ENV_RUN_MODE = "key_env_run";
public String mFilename; private int mFileNameYear; private int mFileNameMonth; private int mFileNameDay; private int mFileNameCount;
public static final String SAVE_FILE_YEAR = "sava_file_year"; public static final String SAVE_FILE_MONTH = "sava_file_month"; public static final String SAVE_FILE_DATE = "sava_file_date"; public static final String SAVE_FILE_COUNT = "sava_file_count";
private String mFileimageRoute = "/sdcard/mnt/camera/DCIM/";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
mPreview = (Preview)findViewById(R.id.camera_preview);
mImageData = new byte[6][];
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (mPreview.mCamera != null) {
mPreview.mCamera.takePicture(mShutterCallback, mPictureCallbackRaw,
mPictureCallbackJpeg);
}
}
return false; }
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
if (mPreview != null) {
Log.e("onDestroy", "onDestroy...");
if (mPreview.mCamera != null) {
mPreview.mCamera.stopPreview();
mPreview.mCamera.release();
mPreview.mCamera = null;
}
}
super.onDestroy();
}
private int getPreFileName() {
if (sPrefs == null) {
sPrefs = getSharedPreferences(KEY_POPUP_ENV, Context.MODE_PRIVATE);
}
mFileNameYear = sPrefs.getInt(SAVE_FILE_YEAR, 0);
mFileNameMonth = sPrefs.getInt(SAVE_FILE_MONTH, 0);
mFileNameDay = sPrefs.getInt(SAVE_FILE_DATE, 0);
mFileNameCount = sPrefs.getInt(SAVE_FILE_COUNT, 0);
return mFileNameCount;
}
private String getRealFileName() {
MakeFileName_Demo();
return mFilename;
}
private void MakeFileName_Demo() {
DecimalFormat decimalFormat = new DecimalFormat("00");// decimalformat
DecimalFormat NumFormat = new DecimalFormat("0000");// 4자리로 표현 한다.
Calendar rightNow = Calendar.getInstance();// 날짜 불러오는 함수
int year = rightNow.get(Calendar.YEAR) % 100;// 100을 나눠서 년도표시를 2009->9지만 decimal포멧으로 09로 표현
int month = rightNow.get(Calendar.MONTH);// 달
int date = rightNow.get(Calendar.DATE);// 일
int num = getPreFileName(); // xml에 저장 되어있는 인덱스 값을 넣는다.
String result =decimalFormat.format(month) + decimalFormat.format(date);
/* 날짜는 00형식 이지만 인덱스는 0000형식 이라서 따로 포멧 저장 */
String FormatNum = NumFormat.format(num);
mFilename = result + "_" + FormatNum;
File[] files = new File("/sdcard/camera/image").listFiles();
if (files.length == 0) {
num++;
} else if (files.length > 0) {
if (CompareDate(year, month, date) == true) {
num++;
} else if (CompareDate(year, month, date) == false) {
num = 0;
}
}
SaveFileName(year, month, date, num);// xml에 저장 }
private boolean CompareDate(int year, int month, int date) {
boolean ret = false;
if (year == getFileNameYear()) {
if (month == getFileNameMonth()) {
if (date == getFileNameDay()) {
ret = true;
}
}
}
return ret; }
private int getFileNameYear() {
return mFileNameYear;
}
private int getFileNameMonth() {
return mFileNameMonth;
}
private int getFileNameDay() {
return mFileNameDay;
}
private void SaveFileName(int year, int month, int date, int num) {
// XML에 저장 putInt...
SharedPreferences.Editor editor = sPrefs.edit();
// putInt(값을 받을 환경변수 , 값을 얻어오는 인자값)
editor.putInt(SAVE_FILE_YEAR, year);
editor.putInt(SAVE_FILE_MONTH, month);
editor.putInt(SAVE_FILE_DATE, date);
editor.putInt(SAVE_FILE_COUNT, num);
editor.commit();// 저장할땐 반드시 commit()을 시킨다.
}
public int SaveImage() {
int ret = 0;
try {
FileOutputStream fileoutstream = new FileOutputStream(mFileimageRoute+getRealFileName()+".jpg");
fileoutstream.write(mImageData[0]);
fileoutstream.close();
System.gc();
}
catch (FileNotFoundException fne)
{
Log.e("writing and scanning image ", fne.toString());
fne.printStackTrace();
ret = -1;
}
catch (IOException ioe)
{
Log.e("writing and scanning image ", ioe.toString());
ioe.printStackTrace();
ret = -1;
} catch (Exception e)
{
ret = -1;
}
return ret;
}
Camera.PictureCallback mPictureCallbackRaw = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera c) {
Log.e("mPictureCallbackRaw ", "11111");
} };
Camera.PictureCallback mPictureCallbackJpeg = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera c) {
Log.e("PictureCallback ", "11111");
Log.e("PictureCallback ", "22222");
mImageData[0] = data;
Display defaultDisplay = ((WindowManager) getSystemService(WINDOW_SERVICE))
.getDefaultDisplay();
int width = defaultDisplay.getWidth();
int height = defaultDisplay.getHeight();
Log.e(String.valueOf(width), String.valueOf(height));
Log.e(String.valueOf(width), String.valueOf(height));
Log.e(String.valueOf(width), String.valueOf(height));
ShowSaveDailog();
}
};
Camera.ShutterCallback mShutterCallback = new Camera.ShutterCallback() {
public void onShutter() {
Log.i(getClass().getSimpleName(), "SHUTTER CALLBACK");
}
};
Camera.AutoFocusCallback cb = new Camera.AutoFocusCallback() {
public void onAutoFocus(boolean success, Camera c) {
Log.e("AutoFocusCallback ", "11111");
if (success) {
ToneGenerator tg = new ToneGenerator(
AudioManager.STREAM_SYSTEM, 100);
if (tg != null)
tg.startTone(ToneGenerator.TONE_PROP_BEEP2);
gFocussed = true;
try {
if (gCameraPressed) {
if (mPreview.mCamera != null) {
mPreview.mCamera.takePicture(mShutterCallback,
mPictureCallbackRaw, mPictureCallbackJpeg);
}
}
} catch (Exception e) {
Log.i("Exc", e.toString());
}
} else {
ToneGenerator tg = new ToneGenerator(
AudioManager.STREAM_SYSTEM, 100);
if (tg != null)
tg.startTone(ToneGenerator.TONE_PROP_BEEP2);
try {
if (gCameraPressed) {
if (mPreview.mCamera != null) {
mPreview.mCamera.takePicture(mShutterCallback,
mPictureCallbackRaw, mPictureCallbackJpeg);
}
}
} catch (Exception e) {
Log.i("Exc", e.toString());
}
}
} };
private void ShowSaveDailog() {
Toast.makeText(this, "save image", Toast.LENGTH_SHORT).show();
SaveImage();
mImageData[0] = null;
if (mPreview.mCamera != null) {
// mPreview.mCamera.lock();
try{
mPreview.mCamera.startPreview();
}
catch (Exception e) {
}
}
}
}CameraPreview.java
import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.text.DecimalFormat; import java.util.Calendar; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.hardware.Camera; import android.media.AudioManager; import android.media.ToneGenerator; import android.os.Bundle; import android.util.Log; import android.view.Display; import android.view.MotionEvent; import android.view.WindowManager; import android.widget.Toast;
public class CameraActivity extends Activity {
private Preview mPreview;
private byte[][] mImageData;
private boolean gFocussed = false;
private boolean gCameraPressed = false;
private static SharedPreferences sPrefs = null; public static final String KEY_POPUP_ENV = "key_env"; public static final String KEY_POPUP_ENV_RUN_MODE = "key_env_run";
public String mFilename; private int mFileNameYear; private int mFileNameMonth; private int mFileNameDay; private int mFileNameCount;
public static final String SAVE_FILE_YEAR = "sava_file_year"; public static final String SAVE_FILE_MONTH = "sava_file_month"; public static final String SAVE_FILE_DATE = "sava_file_date"; public static final String SAVE_FILE_COUNT = "sava_file_count";
private String mFileimageRoute = "/sdcard/mnt/camera/DCIM/";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
mPreview = (Preview)findViewById(R.id.camera_preview);
mImageData = new byte[6][];
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (mPreview.mCamera != null) {
mPreview.mCamera.takePicture(mShutterCallback, mPictureCallbackRaw,
mPictureCallbackJpeg);
}
}
return false; }
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
if (mPreview != null) {
Log.e("onDestroy", "onDestroy...");
if (mPreview.mCamera != null) {
mPreview.mCamera.stopPreview();
mPreview.mCamera.release();
mPreview.mCamera = null;
}
}
super.onDestroy();
}
private int getPreFileName() {
if (sPrefs == null) {
sPrefs = getSharedPreferences(KEY_POPUP_ENV, Context.MODE_PRIVATE);
}
mFileNameYear = sPrefs.getInt(SAVE_FILE_YEAR, 0);
mFileNameMonth = sPrefs.getInt(SAVE_FILE_MONTH, 0);
mFileNameDay = sPrefs.getInt(SAVE_FILE_DATE, 0);
mFileNameCount = sPrefs.getInt(SAVE_FILE_COUNT, 0);
return mFileNameCount;
}
private String getRealFileName() {
MakeFileName_Demo();
return mFilename;
}
private void MakeFileName_Demo() {
DecimalFormat decimalFormat = new DecimalFormat("00");// decimalformat
DecimalFormat NumFormat = new DecimalFormat("0000");// 4자리로 표현 한다.
Calendar rightNow = Calendar.getInstance();// 날짜 불러오는 함수
int year = rightNow.get(Calendar.YEAR) % 100;// 100을 나눠서 년도표시를 2009->9지만 decimal포멧으로 09로 표현
int month = rightNow.get(Calendar.MONTH);// 달
int date = rightNow.get(Calendar.DATE);// 일
int num = getPreFileName(); // xml에 저장 되어있는 인덱스 값을 넣는다.
String result =decimalFormat.format(month) + decimalFormat.format(date);
/* 날짜는 00형식 이지만 인덱스는 0000형식 이라서 따로 포멧 저장 */
String FormatNum = NumFormat.format(num);
mFilename = result + "_" + FormatNum;
File[] files = new File("/sdcard/camera/image").listFiles();
if (files.length == 0) {
num++;
} else if (files.length > 0) {
if (CompareDate(year, month, date) == true) {
num++;
} else if (CompareDate(year, month, date) == false) {
num = 0;
}
}
SaveFileName(year, month, date, num);// xml에 저장 }
private boolean CompareDate(int year, int month, int date) {
boolean ret = false;
if (year == getFileNameYear()) {
if (month == getFileNameMonth()) {
if (date == getFileNameDay()) {
ret = true;
}
}
}
return ret; }
private int getFileNameYear() {
return mFileNameYear;
}
private int getFileNameMonth() {
return mFileNameMonth;
}
private int getFileNameDay() {
return mFileNameDay;
}
private void SaveFileName(int year, int month, int date, int num) {
// XML에 저장 putInt...
SharedPreferences.Editor editor = sPrefs.edit();
// putInt(값을 받을 환경변수 , 값을 얻어오는 인자값)
editor.putInt(SAVE_FILE_YEAR, year);
editor.putInt(SAVE_FILE_MONTH, month);
editor.putInt(SAVE_FILE_DATE, date);
editor.putInt(SAVE_FILE_COUNT, num);
editor.commit();// 저장할땐 반드시 commit()을 시킨다.
}
public int SaveImage() {
int ret = 0;
try {
FileOutputStream fileoutstream = new FileOutputStream(mFileimageRoute+getRealFileName()+".jpg");
fileoutstream.write(mImageData[0]);
fileoutstream.close();
System.gc();
}
catch (FileNotFoundException fne)
{
Log.e("writing and scanning image ", fne.toString());
fne.printStackTrace();
ret = -1;
}
catch (IOException ioe)
{
Log.e("writing and scanning image ", ioe.toString());
ioe.printStackTrace();
ret = -1;
} catch (Exception e)
{
ret = -1;
}
return ret;
}
Camera.PictureCallback mPictureCallbackRaw = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera c) {
Log.e("mPictureCallbackRaw ", "11111");
} };
Camera.PictureCallback mPictureCallbackJpeg = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera c) {
Log.e("PictureCallback ", "11111");
Log.e("PictureCallback ", "22222");
mImageData[0] = data;
Display defaultDisplay = ((WindowManager) getSystemService(WINDOW_SERVICE))
.getDefaultDisplay();
int width = defaultDisplay.getWidth();
int height = defaultDisplay.getHeight();
Log.e(String.valueOf(width), String.valueOf(height));
Log.e(String.valueOf(width), String.valueOf(height));
Log.e(String.valueOf(width), String.valueOf(height));
ShowSaveDailog();
}
};
Camera.ShutterCallback mShutterCallback = new Camera.ShutterCallback() {
public void onShutter() {
Log.i(getClass().getSimpleName(), "SHUTTER CALLBACK");
}
};
Camera.AutoFocusCallback cb = new Camera.AutoFocusCallback() {
public void onAutoFocus(boolean success, Camera c) {
Log.e("AutoFocusCallback ", "11111");
if (success) {
ToneGenerator tg = new ToneGenerator(
AudioManager.STREAM_SYSTEM, 100);
if (tg != null)
tg.startTone(ToneGenerator.TONE_PROP_BEEP2);
gFocussed = true;
try {
if (gCameraPressed) {
if (mPreview.mCamera != null) {
mPreview.mCamera.takePicture(mShutterCallback,
mPictureCallbackRaw, mPictureCallbackJpeg);
}
}
} catch (Exception e) {
Log.i("Exc", e.toString());
}
} else {
ToneGenerator tg = new ToneGenerator(
AudioManager.STREAM_SYSTEM, 100);
if (tg != null)
tg.startTone(ToneGenerator.TONE_PROP_BEEP2);
try {
if (gCameraPressed) {
if (mPreview.mCamera != null) {
mPreview.mCamera.takePicture(mShutterCallback,
mPictureCallbackRaw, mPictureCallbackJpeg);
}
}
} catch (Exception e) {
Log.i("Exc", e.toString());
}
}
} };
private void ShowSaveDailog() {
Toast.makeText(this, "save image", Toast.LENGTH_SHORT).show();
SaveImage();
mImageData[0] = null;
if (mPreview.mCamera != null) {
// mPreview.mCamera.lock();
try{
mPreview.mCamera.startPreview();
}
catch (Exception e) {
}
}
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<co.kr.hotjellysoftware.NFCM.CameraPreview
android:id="@+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
메니페스트
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="co.kr.hotjellysoftware.NFCM"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="10" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".Firstpage"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".CameraActivity"></activity>
</application>
<uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>
<uses-permission android:name="android.permission.RECORD_VIDEO"></uses-permission>
<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-feature android:name="android.hardware.camera"></uses-feature>
<uses-permission android:name="android.permission.CAMERA"></uses-permission>
</manifest>
감사합니다.
2011.11.06 20:15:14
간단히 말하면 지금 main.xml을 보시면 안에 co.kr.hotjellysoftware.NFCM.CameraPreview
태그로 만들어 두신게 있습니다.. 그러나 이것은 커스텀뷰를 칭하는것이지 액티비티를 칭하는게 아닙니다.. 이부분이 잘못되었
다는 이야기입니다.. 해결하시려면
액티비티에서 카메라뷰를 붙여놓은 액티비티로 이동해서 보여주거나 또는
카메라뷰의 상속을 액티비티가 아닌 뷰로 상속을 받아야하고.. 이때 해당 소스에는 액티비티와 관련된 소스는 당연히
지워야합니다. (뷰에는 onCreate onDestory같은거 없습니다. 그러니 당연히 줄줄이 에러가 나지요)
액티비티와 뷰의 차이점에 대해서 다시 공부하시라는건 그런 연유입니다.




CameraPreView는 뷰인데 왜 Activity를 상속받아는지이해가 안가네여... View 를 상속받고 하시고
슈퍼클래스 작성하시기 바랍니다..액티비티와 뷰에대한 차이점을 알고 계셔야할거 같습니다.