撮からカメラなプレビュー
-
24-09-2019 - |
質問
皆様にお伝えしたくて書き込み、Android1.5が適用開始直後に起動します。この Service
やるべきくプレビューします。本アプリケーションは、アプリ内のログの光密度は一部の地域である。より品切れとなってしまう場合も画像が映します。
後の研究に長時間かのバグのスレッドです。ない場合を生成するプレビュー画像が黒色からAndroidのカメラのニーズをプレビューの設定を暴露す。私 SurfaceView
のリスナーが、 onSurfaceCreated()
イベントないください。
しないといけないのではないかその理由は、表面が作成できます。私も見た事例の呼び出しカメラ静的 MediaStore.CAPTURE_OR_SOMETHING
かかる写真を保存し、ご希望のフォルダのコードなどの写真も撮ります。
使ったらよいでしIPC、 bindService()
これはも機能しているのでしょうか。その代替的な方法を実現。
解決
有効なプレビュー表面を与えまで、Androidプラットフォーム上のカメラはビデオをストリームすることができないということは本当に奇妙です。プラットフォームのアーキテクトは、すべてのアプリケーションをストリーミングサードパーティのビデオについて考えていませんでしたようです。でも拡張現実ケースのための画像は、視覚的な置換のいくつかの種類ではなく、リアルタイムのカメラストリームとして提示することができます。
とにかく、あなたは、単に の1×1ピクセルにプレビュー表面のサイズを変更することができますし、ウィジェット(ビジュアル要素)の隅のどこかにそれを置きます。してください注意を払う - 。リサイズプレビュー表面ではなく、カメラのフレームサイズ
もちろん、このようなトリックは、いくつかのシステムリソースとバッテリーを消費する(プレビュー用)ストリーミング不要なデータを排除しません。
他のヒント
私は Androidのカメラドキュメントの中でこれに対する答えを見つけました。
注:カメラを作成せずに
MediaRecorder
を使用することが可能です 最初のプレビューと、このプロセスの最初の数ステップをスキップします。しかしながら、 ユーザーは一般的にAを開始する前にプレビューを表示することを好むので、 記録、そのプロセスは、ここで議論されていません。
あなたは上記のリンクでステップバイステップのインストラクションを見つけることができます。指示した後、それは私が上方に設けられていることを引用符を述べます。
実際にキャンセルは可能ですが、い偽のプレビューとダミー SurfaceView
SurfaceView view = new SurfaceView(this);
c.setPreviewDisplay(view.getHolder());
c.startPreview();
c.takePicture(shutterCallback, rawPictureCallback, jpegPictureCallback);
更新9/21/11: どうやらこれは動作しない毎Android装置です。
写真を撮影
この作業の前にいhideのプレビューします。
- 正しくセットのプレビュー
- を使用
SurfaceView
(事前Android4.0compatibility)SurfaceTexture
(Android4+は、透明) - 設定initialiseで写真を撮影する前に
- 待ちに
SurfaceView
'sSurfaceHolder
(getHolder()
報surfaceCreated()
またはTextureView
報告onSurfaceTextureAvailable
そのSurfaceTextureListener
前設定値及びinitialisingのプレビューします。
- を使用
- を確保するプレビューが見える:
- 追加する
WindowManager
- の確保、そのレイアウトサイズは少なくとも1×1ピクセル(い開始により
MATCH_PARENT
xMATCH_PARENT
試験) - の確保、視認性が
View.VISIBLE
るようにデフォルトを特に指定しない場合) - をご利用の
FLAG_HARDWARE_ACCELERATED
のLayoutParams
場合でTextureView
.
- 追加する
- 使用
takePicture
's JPEGコールバックから文書によると、その他のコールバックなサポートされてすべてのデバイス
トラブ
- の場合
surfaceCreated
/onSurfaceTextureAvailable
がないという、SurfaceView
/TextureView
と思われていて、現在停止している表示されます。 - の場合
takePicture
に失敗した場合、初めのプレビューが正常に動作して.削除ができますtakePicture
電話でのプレビュー走行もしくはディスプレイの画面になります。 - 場合、画像は暗めのあるべき姿に必要がある場合がありますの遅延程の次の呼び出しの前に
takePicture
このカメラの調整に時間のエクスポージャーのプレビューを開始しました。
隠され、プレビュー
のプレビュー
View
1x1サイズを最小限に抑えるためには、その視認性(み8x16は不可能で高い信頼性を)new WindowManager.LayoutParams(1, 1, /*...*/)
移動プレビュー中心に削減をnoticeability:
new WindowManager.LayoutParams(width, height, Integer.MIN_VALUE, Integer.MIN_VALUE, /*...*/)
のプレビュー透明のみ動作
TextureView
)WindowManager.LayoutParams params = new WindowManager.LayoutParams( width, height, /*...*/ PixelFormat.TRANSPARENT); params.alpha = 0;
実施例(テソニー Xperia M、Android4.3)
/** Takes a single photo on service start. */
public class PhotoTakingService extends Service {
@Override
public void onCreate() {
super.onCreate();
takePhoto(this);
}
@SuppressWarnings("deprecation")
private static void takePhoto(final Context context) {
final SurfaceView preview = new SurfaceView(context);
SurfaceHolder holder = preview.getHolder();
// deprecated setting, but required on Android versions prior to 3.0
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
holder.addCallback(new Callback() {
@Override
//The preview must happen at or after this point or takePicture fails
public void surfaceCreated(SurfaceHolder holder) {
showMessage("Surface created");
Camera camera = null;
try {
camera = Camera.open();
showMessage("Opened camera");
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
throw new RuntimeException(e);
}
camera.startPreview();
showMessage("Started preview");
camera.takePicture(null, null, new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
showMessage("Took picture");
camera.release();
}
});
} catch (Exception e) {
if (camera != null)
camera.release();
throw new RuntimeException(e);
}
}
@Override public void surfaceDestroyed(SurfaceHolder holder) {}
@Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
});
WindowManager wm = (WindowManager)context
.getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
1, 1, //Must be at least 1x1
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
0,
//Don't know if this is a safe default
PixelFormat.UNKNOWN);
//Don't set the preview visibility to GONE or INVISIBLE
wm.addView(preview, params);
}
private static void showMessage(String message) {
Log.i("Camera", message);
}
@Override public IBinder onBind(Intent intent) { return null; }
}
でAndroid 4.0以上(APIレベル> = 14)は、を使用することができますTextureViewするにプレビューカメラのストリームと、それをユーザーに表示しないようにと、それは見えないようにしてください。ここでの方法:
まず、プレビュー、表面のために作成/更新コールバックを取得しますSurfaceTextureListenerを実装するクラスを作成します。このクラスはまた、表面が作成されると、それはすぐにカメラのstartPreview関数を呼び出すことができるように、入力として、カメラオブジェクトを取ります:
public class CamPreview extends TextureView implements SurfaceTextureListener {
private Camera mCamera;
public CamPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
setLayoutParams(new FrameLayout.LayoutParams(
previewSize.width, previewSize.height, Gravity.CENTER));
try{
mCamera.setPreviewTexture(surface);
} catch (IOException t) {}
mCamera.startPreview();
this.setVisibility(INVISIBLE); // Make the surface invisible as soon as it is created
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Put code here to handle texture size change if you want to
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// Update your view here!
}
}
また、プレビューデータを処理するために、コールバッククラスを実装する必要があります:
public class CamCallback implements Camera.PreviewCallback{
public void onPreviewFrame(byte[] data, Camera camera){
// Process the camera data here
}
}
あなたの活動ののonCreate()または同様のスタートアップ関数で使用上のCamPreviewとCamCallbackクラスのセットアップにカメラます:
// Setup the camera and the preview object
Camera mCamera = Camera.open(0);
CamPreview camPreview = new CamPreview(Context,mCamera);
camPreview.setSurfaceTextureListener(camPreview);
// Connect the preview object to a FrameLayout in your UI
// You'll have to create a FrameLayout object in your UI to place this preview in
FrameLayout preview = (FrameLayout) findViewById(R.id.cameraView);
preview.addView(camPreview);
// Attach a callback for preview
CamCallback camCallback = new CamCallback();
mCamera.setPreviewCallback(camCallback);
はこれを行う方法がありますが、それはややトリッキーです。 何を行うべきであることは、サービスからウィンドウマネージャにsurfaceholderを添付している。
WindowManager wm = (WindowManager) mCtx.getSystemService(Context.WINDOW_SERVICE);
params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
wm.addView(surfaceview, params);
その後、と
設定surfaceview.setZOrderOnTop(true);
mHolder.setFormat(PixelFormat.TRANSPARENT);
mHolderはあなたが表面ビューから取得するホルダーです。
この方法で、あなたは、surfaceviewのアルファで遊ぶことがcompletly透明にするが、カメラはまだフレームを取得することができます。
私はそれを行う方法です。。それが役に立てば幸い:)
私たちは、3.0(またはのは、タブレット上のカメラサービスとして4.0が本当に意味がないとしましょう)以下のバージョンでは(実際のGUIに追加されていない)ダミーSurfaceViewを使用することによって、この問題を解決しました。 バージョンでは> = 4.0は、これが唯一のエミュレータで働いていました。( SurfaceTexture(およびsetSurfaceTexture())の代わりにSurfaceView(およびsetSurfaceView())の使用は、ここで働いていました。ネクサスS上に少なくともこの作品ます。
私はこれは本当にAndroidのフレームワークの欠点だと思います。
"サムによって実施例" では、
(あなたのサムを...ありがとうございました)istructionであれば "wm.addView(プレビュー、paramsは);"
例外を取得「ウィンドウandroid.view.ViewRootを追加できません - このウィンドウタイプのために拒否された権限」
AndroidManifestにこの権限を使用して解決ます:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
あなたは、キャプチャ、バックカメラ、その後映像コードやコメントfrontCameraでコメントを解除backCameraをしたい場合は、このサービスは、フロント画像をクリックして、この作業のコードを試すことができます。
注: - 活動や、どこからでもAPPおよびSTARTSERVICEにカメラとストレージ権限を許可します。
public class MyService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
CapturePhoto();
}
private void CapturePhoto() {
Log.d("kkkk","Preparing to take photo");
Camera camera = null;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
int frontCamera = 1;
//int backCamera=0;
Camera.getCameraInfo(frontCamera, cameraInfo);
try {
camera = Camera.open(frontCamera);
} catch (RuntimeException e) {
Log.d("kkkk","Camera not available: " + 1);
camera = null;
//e.printStackTrace();
}
try {
if (null == camera) {
Log.d("kkkk","Could not get camera instance");
} else {
Log.d("kkkk","Got the camera, creating the dummy surface texture");
try {
camera.setPreviewTexture(new SurfaceTexture(0));
camera.startPreview();
} catch (Exception e) {
Log.d("kkkk","Could not set the surface preview texture");
e.printStackTrace();
}
camera.takePicture(null, null, new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFileDir=new File("/sdcard/CaptureByService");
if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {
pictureFileDir.mkdirs();
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
String date = dateFormat.format(new Date());
String photoFile = "ServiceClickedPic_" + "_" + date + ".jpg";
String filename = pictureFileDir.getPath() + File.separator + photoFile;
File mainPicture = new File(filename);
try {
FileOutputStream fos = new FileOutputStream(mainPicture);
fos.write(data);
fos.close();
Log.d("kkkk","image saved");
} catch (Exception error) {
Log.d("kkkk","Image could not be saved");
}
camera.release();
}
});
}
} catch (Exception e) {
camera.release();
}
}
}