책에 있는 소스 그대로 긁어 왔는데 이상하게 실행이 안됩니다.

permission도 확실히 확인했고 액티비티도 하나뿐인데 이상하군요

아래 참고 소스입니다..


package com.example.testcamera;

import java.io.*;

import java.util.*;

import android.app.*;

import android.content.*;

import android.graphics.*;

import android.hardware.Camera;

import android.hardware.Camera.*;

import android.net.*;

import android.os.*;

import android.util.*;

import android.view.*;

import android.widget.*;


public class MainActivity extends Activity {

String mRootPath;

LinearLayout mTakePicture;

ImageView mReview;

SHCameraSurface mSurface;

int mPicWidth, mPicHeight;

int mSelect;

String mLastPicture = "";

static final String PICFOLDER = "SHCamera";

static final int TAKEDELAY = 300;

Context mMainContext;


public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

requestWindowFeature(Window.FEATURE_NO_TITLE);

setContentView(R.layout.activity_main);

mMainContext = this;

// SD 카드가 없을 시 에러 처리한다.

String ext = Environment.getExternalStorageState();

if (ext.equals(Environment.MEDIA_MOUNTED) == false) {

Toast.makeText(this, "SD 카드가 반드시 필요합니다.", 1).show();

finish();

return;

}

mRootPath = Environment.getExternalStorageDirectory().getAbsolutePath() + 

"/" + PICFOLDER;

File fRoot = new File(mRootPath);

if (fRoot.exists() == false) {

if (fRoot.mkdir() == false) {

Toast.makeText(this, "사진을 저장할 폴더가 없습니다.", 1).show();

finish();

return;

}

}

// 프레퍼런스에서 크기 읽어 옴

SharedPreferences pref = getSharedPreferences("SHCamera",0);

mPicWidth = pref.getInt("PicWidth", -1);

mPicHeight = pref.getInt("PicHeight", -1);


// 버튼들의 클릭 리스너 지정

mTakePicture = (LinearLayout)findViewById(R.id.takepicture);

mReview = (ImageView)findViewById(R.id.imgreview);

mSurface = (SHCameraSurface)findViewById(R.id.preview);

findViewById(R.id.btnsize).setOnClickListener(mSizeClick);

findViewById(R.id.btnreview).setOnClickListener(mReviewClick);

findViewById(R.id.btntake).setOnClickListener(mTakeClick);

((CheckBox)findViewById(R.id.btnmacro)).setOnCheckedChangeListener(toggleMacro);

}


public void onDestroy() {

super.onDestroy();

}


// 사진 확인 상태에서 Back누르면 촬영 모드로 전환

public boolean onKeyUp (int keyCode, KeyEvent event) {

if (keyCode == KeyEvent.KEYCODE_BACK && mReview.getVisibility() == View.VISIBLE) {

mReview.setVisibility(View.GONE);

mTakePicture.setVisibility(View.VISIBLE);

return true;

} else {

super.onKeyUp(keyCode, event);

return false;

}

}


// 사진 촬영

Button.OnClickListener mTakeClick = new Button.OnClickListener() {

public void onClick(View v) {

mSurface.mCamera.autoFocus(mAutoFocus);

}

};

// 포커싱 성공하면 촬영

AutoFocusCallback mAutoFocus = new AutoFocusCallback() {

public void onAutoFocus(boolean success, Camera camera) {

if (success) {

mTakePicture.postDelayed(new Runnable() {

public void run() {

mSurface.mCamera.takePicture(null, null, mPicture);

}

}, TAKEDELAY);

} else {

Toast.makeText(mMainContext, "초점을 잡을 수 없습니다.", 1).show();

}

}

};


// 사진 저장. 날짜와 시간으로 파일명 결정하고 저장후 미디어 스캔 실행

PictureCallback mPicture = new PictureCallback() {

public void onPictureTaken(byte[] data, Camera camera) {

Calendar calendar = Calendar.getInstance();

String FileName = String.format("SH%02d%02d%02d-%02d%02d%02d.jpg", 

calendar.get(Calendar.YEAR) % 100, calendar.get(Calendar.MONTH)+1, 

calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY), 

calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND));

String path = mRootPath + "/" + FileName;


File file = new File(path);

try {

FileOutputStream fos = new FileOutputStream(file);

fos.write(data);

fos.flush();

fos.close();

} catch (Exception e) {

Toast.makeText(mMainContext, "파일 저장 중 에러 발생 : " + 

e.getMessage(), 0).show();

return;

}


// 스캐닝 요청

Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);

Uri uri = Uri.parse("file://" + path);

intent.setData(uri);

sendBroadcast(intent);


mLastPicture = path;

mSurface.mCamera.startPreview();

}

};

// 크기 변경

Button.OnClickListener mSizeClick = new Button.OnClickListener() {

public void onClick(View v) {

Parameters params = mSurface.mCamera.getParameters();

       final List<Size> arSize = params.getSupportedPictureSizes();

       String[] arName = new String[arSize.size()];

       for (int i = 0; i < arSize.size(); i++) {

        Size s = arSize.get(i);

        arName[i] = String.format("%d * %d", s.width, s.height);

        if (mPicWidth == s.width && mPicHeight == s.height) {

        mSelect = i;

        }

       }

       

new AlertDialog.Builder(mMainContext)

.setTitle("사진 해상도 선택")

.setSingleChoiceItems(arName, mSelect, new DialogInterface.OnClickListener() {

public void onClick(DialogInterface dialog, int which) {

mSelect = which;

}

})

.setPositiveButton("확인", new DialogInterface.OnClickListener() {

public void onClick(DialogInterface dialog, int whichButton) {

Parameters params = mSurface.mCamera.getParameters();

int width = arSize.get(mSelect).width;

int height = arSize.get(mSelect).height;

params.setPictureSize(width, height);

mSurface.mCamera.setParameters(params);


SharedPreferences pref = getSharedPreferences("SHCamera",0);

SharedPreferences.Editor edit = pref.edit();

edit.putInt("PicWidth", width);

edit.putInt("PicHeight", height);

edit.commit();

}

})

.setNegativeButton("취소", null)

.show();

}

};

// 사진 확인

Button.OnClickListener mReviewClick = new Button.OnClickListener() {

public void onClick(View v) {

if (mLastPicture.length() != 0) {

mReview.setVisibility(View.VISIBLE);

mTakePicture.setVisibility(View.GONE);

try {

BitmapFactory.Options opt = new BitmapFactory.Options();

opt.inSampleSize = 4;

Bitmap bm = BitmapFactory.decodeFile(mLastPicture, opt);

mReview.setImageBitmap(bm);

}

catch (OutOfMemoryError e) {

Toast.makeText(mMainContext,"이미지를 읽을 수 없습니다", 0).show();

}

mReview.setOnTouchListener(new View.OnTouchListener() {

public boolean onTouch(View v, MotionEvent event) {

mReview.setVisibility(View.GONE);

mTakePicture.setVisibility(View.VISIBLE);

return false;

}

});

} else {

Toast.makeText(mMainContext,"아직 찍은 사진이 없습니다.",

Toast.LENGTH_SHORT).show();

}

}

}; 


// 매크로 모드 토글

CompoundButton.OnCheckedChangeListener toggleMacro = new CompoundButton.OnCheckedChangeListener() {

public void onCheckedChanged (CompoundButton buttonView, boolean isChecked) {

if (buttonView.getId() == R.id.btnmacro) {

if (isChecked) {

Parameters params = mSurface.mCamera.getParameters();

params.setFocusMode(Camera.Parameters.FOCUS_MODE_MACRO);

mSurface.mCamera.setParameters(params);

} else {

Parameters params = mSurface.mCamera.getParameters();

params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);

mSurface.mCamera.setParameters(params);

}

}

}

};

public boolean onCreateOptionsMenu(Menu menu) {

super.onCreateOptionsMenu(menu);

menu.add(0,1,0,"소개");

menu.add(0,2,0,"종료");


return true;

}


public boolean onOptionsItemSelected(MenuItem item) {

switch (item.getItemId()) {

case 1:

    new AlertDialog.Builder(this)

    .setTitle("프로그램 소개")

    .setMessage("이 프로그램은 필수 기능만 제공하는 카메라입니다. 기존 카메라는 화면의 셔터 버튼을 " + 

    "놓을 때 장비의 떨림으로 인해 사진의 정확도가 떨어지나 이 프로그램은 터치를 놓은 후 초점을 " + 

    "맞추고 잠시 대기 후 사진을 찍어 선명도를 극대화합니다. 잘생긴 사람은 누구나 무료로 사용할 수 있습니다.")

    .setPositiveButton("닫기", null)

    .show();

return true;

case 2:

finish();

System.exit(0);

return true;

}

return false;

}

}


// 미리보기 표면 클래스

class SHCameraSurface extends SurfaceView implements SurfaceHolder.Callback {

SurfaceHolder mHolder;

Context mContext;

Camera mCamera;


public SHCameraSurface(Context context) {

super(context);

init(context);

}


public SHCameraSurface(Context context, AttributeSet attrs) {

super(context, attrs);

init(context);

}


public SHCameraSurface(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

init(context);

}


void init(Context context) {

mContext = context;

mHolder = getHolder();

mHolder.addCallback(this);

mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

}


// 표면 생성시 카메라 오픈하고 미리보기 설정

public void surfaceCreated(SurfaceHolder holder) {

mCamera = Camera.open();

try {

mCamera.setPreviewDisplay(mHolder);

} catch (IOException e) {

mCamera.release();

mCamera = null;

}

}


    // 표면 파괴시 카메라도 파괴한다.

public void surfaceDestroyed(SurfaceHolder holder) {

if (mCamera != null) {

mCamera.stopPreview();

mCamera.release();

mCamera = null;

}

}


// 표면의 크기가 결정될 때 최적의 미리보기 크기를 구해 설정한다.

    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

Camera.Parameters params = mCamera.getParameters();

        List<Size> arSize = params.getSupportedPreviewSizes();

        if (arSize == null) {

params.setPreviewSize(width, height);

        } else {

       int diff = 10000;

       Size opti = null;

       for (Size s : arSize) {

        if (Math.abs(s.height - height) < diff) {

        diff = Math.abs(s.height - height);

        opti = s;

       

        }

       }

params.setPreviewSize(opti.width, opti.height);

        }

        

        MainActivity SHCamera = (MainActivity)mContext;

        if (SHCamera.mPicWidth != -1) {

params.setPictureSize(SHCamera.mPicWidth, SHCamera.mPicHeight);

        }

mCamera.setParameters(params);

mCamera.startPreview();

}

}

 

 <?xml version="1.0" encoding="utf-8"?>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

>

<ImageView

    android:id="@+id/imgreview"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    android:visibility="invisible"

/>

<LinearLayout 

    android:id="@+id/takepicture"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    >

<exam.andexam.SHCameraSurface

    android:id="@+id/preview"

    android:layout_width="350dip" 

    android:layout_height="fill_parent"

    android:layout_weight="3" 

    />

<RelativeLayout

    android:layout_width="130dip"

    android:layout_height="fill_parent"

    android:background="#404040"

    android:layout_weight="1" 

    >

<Button 

    android:id="@+id/btntake"

    android:layout_alignParentTop="true"

    android:layout_width="fill_parent" 

    android:layout_height="wrap_content" 

    android:text="촬영"

    android:textSize="13pt"

    android:paddingTop="50dip"

    android:paddingBottom="50dip"

    />

<Button 

    android:id="@+id/btnsize"

    android:layout_alignParentBottom="true"

    android:layout_width="fill_parent" 

    android:layout_height="wrap_content" 

    android:text="크기"

    android:textSize="10pt"

    />

<CheckBox 

    android:id="@+id/btnmacro"

    android:layout_above="@id/btnsize"

    android:layout_width="fill_parent" 

    android:layout_height="wrap_content" 

    android:text="접사"

    android:textSize="10pt"

    />

<Button 

    android:id="@+id/btnreview"

    android:layout_above="@id/btnmacro"

    android:layout_width="fill_parent" 

    android:layout_height="wrap_content" 

    android:text="잘찍었나?"

    android:textSize="10pt"

    />

</RelativeLayout>

</LinearLayout>

</FrameLayout>

 <manifest xmlns:android="http://schemas.android.com/apk/res/android"

    package="com.example.testcamera"

    android:versionCode="1"

    android:versionName="1.0" >


    <uses-sdk

        android:minSdkVersion="8"

        android:targetSdkVersion="15" />


    <uses-permission android:name="android.permission.CAMERA"/>

    <uses-feature android:name="android.hardware.camera" />

    <uses-feature android:name="android.hardware.camera.autofocus" />

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    

    <application

        android:icon="@drawable/ic_launcher"

        android:label="@string/app_name" >

        <activity

            android:name=".MainActivity"

            android:label="@string/title_activity_main" 

            android:screenOrientation="landscape" 

        android:configChanges="orientation|keyboardHidden" >

            <intent-filter>

                <action android:name="android.intent.action.MAIN" />


                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

    </application>


</manifest>


위에서부터 차래대로 메인 엑티비티, 레이아웃XML, 메니피스트 입니다.

오류라도 뜨면 확인하겠는데 오류도 안뜨고 그냥 프로그램이 죽어버리니 막막하군요