写真を撮ることができる小さなプログラムを考えてください。
すべての操作は、 Cameraクラスを使用して実行されます。
変数を取得する必要があります
Camera camera;
彼女を初期化する
camera = Camera.open();
カメラでの作業が終了したら、次のことを行う必要があります
camera.release();
そうしないと、カメラはロックされたままになり、他のアプリケーションからアクセスできなくなります。
カメラなどの通常のアプリケーションでは、初期化はonResumeで行い、リリースはonPauseで行うのが最適です 。
カメラを使用する際の前提条件は、プレビューウィンドウ(プレビュー)を作成することです。 このウィンドウはSurfaceクラスのオブジェクトである必要があり、 SurfaceViewは画面での表示に適しています。
発表します
SurfaceView preview;
プレビューを設定するには、パラメーターがSurfaceHolderクラスのオブジェクトであるsetPreviewDisplayメソッドを呼び出す必要があります。
SurfaceHolder surfaceHolder; surfaceHolder = preview.getHolder(); camera.setPreviewDisplay(surfaceHolder);
プレビュー表示を有効にするには、
camera.startPreview();
これが行われない場合、カメラは写真を撮ることができません。
実際に、写真を撮るには、メソッドを呼び出す必要があります
void takePicture(Camera.ShutterCalback shutter, Camera.PictureCallback raw, Camera.PictureCallback postview, Camera.PictureCallback jpg);
パラメーターを使用して(ところで、それらのいずれかがnullになる可能性があります)、さまざまなイベントのハンドラーが設定されます。
- シャッター-画像がマトリックスから受信されたときに呼び出されます
- raw-rawを処理するためにデータがプログラムに渡されます(ハードウェアでサポートされている場合)
- ポストビュー-プログラムは完全に処理されたデータを受け取ります(ハードウェアでサポートされている場合)
- jpg-プログラムはjpg形式の画像を受け取ります。 ここでは、メモリカード上の画像の記録を整理できます。
takePicture呼び出しは、ボタンのonClickハンドラーに直接配置できます。この場合、クリックするとすぐに撮影が行われますが、予備のオートフォーカスを使用することもできます。
この場合、メソッドを実装する必要があるCamera.AutoFocusCallbackハンドラーが設定されます
public void onAutoFocus(boolean paramBoolean, Camera paramCamera);
次に、ハンドラーでcamera.autoFocus()ボタンを呼び出した後、ハンドラーが1回呼び出されます。このハンドラーでは、フォーカスの成功と写真撮影の必要性について既に決定しています。
SurfaceHolderをSurfaceHolderで動作するように設定できます。
surfaceHolder.addCallback();
この場合、メソッドを実装する必要があります
public void surfaceCreated(SurfaceHolder holder); public void surfaceChanged(SurfaceHolder holder, int format, int width, int height); public void surfaceDestroyed(SurfaceHolder holder);
それらを使用して、アプリケーションは、変更された場合または削除された場合にSurfaceが正常に作成されたことを通知されます。
プレビューのサイズは、プログラムの実行中に変更できます。
LayoutParams lp = preview.getLayoutParams(); lp.width = ; lp.height = ; preview.setLayoutParams(lp);
カメラアプリケーションの場合、画面の場所をすぐに設定するのが最も便利です
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
それ以外の場合、たとえばsurfaceCreatedで画面の場所を確認し、たとえば
camera.setDisplayOrientation(0)
を使用してプレビューを回転する必要があります。
画面を回転させるのに時間がかかるため、これはあまり便利ではありません。 この時点で、onPauseとonResumeが呼び出され、Surfaceが再作成されます。
Camera.PreviewCallbackハンドラーを宣言することもできます。これを介してメソッドを実装します
void onPreviewFrame(byte[] paramArrayOfByte, Camera paramCamera);
プレビューに表示される各フレームを受信して処理できます。
そして最後の重要なポイント。 ほとんどの場合、SurfaceViewのアスペクト比はカメラのプレビューのアスペクト比と異なることが判明しています。 したがって、画面上の画像の歪みを回避するために、表示されるプレビューウィンドウのサイズを調整する必要があります。
私はほとんど忘れていました。 マニフェストに許可を追加する必要があります
<uses-permission android:name="android.permission.CAMERA" />
MainScreen.java
package test.camera; import android.app.Activity; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.os.Bundle; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.ViewGroup.LayoutParams; import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.view.View; import android.hardware.Camera; import android.hardware.Camera.Size; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; public class MainScreen extends Activity implements SurfaceHolder.Callback, View.OnClickListener, Camera.PictureCallback, Camera.PreviewCallback, Camera.AutoFocusCallback { private Camera camera; private SurfaceHolder surfaceHolder; private SurfaceView preview; private Button shotBtn; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // , setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); // , getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); // requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.main); // SurfaceView SurfaceView01 preview = (SurfaceView) findViewById(R.id.SurfaceView01); surfaceHolder = preview.getHolder(); surfaceHolder.addCallback(this); surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // Button01 shotBtn = (Button) findViewById(R.id.Button01); shotBtn.setText("Shot"); shotBtn.setOnClickListener(this); } @Override protected void onResume() { super.onResume(); camera = Camera.open(); } @Override protected void onPause() { super.onPause(); if (camera != null) { camera.setPreviewCallback(null); camera.stopPreview(); camera.release(); camera = null; } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceCreated(SurfaceHolder holder) { try { camera.setPreviewDisplay(holder); camera.setPreviewCallback(this); } catch (IOException e) { e.printStackTrace(); } Size previewSize = camera.getParameters().getPreviewSize(); float aspect = (float) previewSize.width / previewSize.height; int previewSurfaceWidth = preview.getWidth(); int previewSurfaceHeight = preview.getHeight(); LayoutParams lp = preview.getLayoutParams(); // preview, if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) { // camera.setDisplayOrientation(90); lp.height = previewSurfaceHeight; lp.width = (int) (previewSurfaceHeight / aspect); ; } else { // camera.setDisplayOrientation(0); lp.width = previewSurfaceWidth; lp.height = (int) (previewSurfaceWidth / aspect); } preview.setLayoutParams(lp); camera.startPreview(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { } @Override public void onClick(View v) { if (v == shotBtn) { // // //camera.takePicture(null, null, null, this); camera.autoFocus(this); } } @Override public void onPictureTaken(byte[] paramArrayOfByte, Camera paramCamera) { // jpg /sdcard/CameraExample/ // - System.currentTimeMillis() try { File saveDir = new File("/sdcard/CameraExample/"); if (!saveDir.exists()) { saveDir.mkdirs(); } FileOutputStream os = new FileOutputStream(String.format("/sdcard/CameraExample/%d.jpg", System.currentTimeMillis())); os.write(paramArrayOfByte); os.close(); } catch (Exception e) { } // , , . paramCamera.startPreview(); } @Override public void onAutoFocus(boolean paramBoolean, Camera paramCamera) { if (paramBoolean) { // , paramCamera.takePicture(null, null, null, this); } } @Override public void onPreviewFrame(byte[] paramArrayOfByte, Camera paramCamera) { // , preview } }
main.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout android:id="@+id/FrameLayout01" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"> <SurfaceView android:id="@+id/SurfaceView01" android:layout_width="wrap_content" android:layout_height="wrap_content"> </SurfaceView> <Button android:text="@+id/Button01" android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content"> </Button> </FrameLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="test.camera" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true"> <activity android:name=".MainScreen" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> </manifest>
プログラムは、電話LG Optimus One P500でデバッグおよびテストされました。
執筆時には、次の情報源が使用されました。
- developer.android.com/reference/android/hardware/Camera.html
- ショーンヴァンエブリィ。 Pro Android Media:スマートフォンとタブレット向けのグラフィックス、音楽、ビデオ、リッチメディアアプリの開発。 Apress 2009。
- developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.html
リンクからプロジェクトをダウンロードできます: ここで 再読み込みzalil.ru/30377379