Androidでバックグラウンド連続サイレント撮影を実現(プレビューなしで点滅しない)

14378 ワード


 
簡単な背景(くだらない話だらけ)
この間、Androidプロジェクトをしていましたが、「バックグラウンド」でフロントカメラを静かに開いて連続的に写真を撮る必要があることについて話しています.
ネット上でいろいろな方法を試したことがありますが、主な方法はプレビューの透明+を小さくすることです(0.1 x 0.1).しかし、この方法ではいわゆる「バックグラウンド」効果を実現することはできません.透明なインタフェースでは何もできません.インタラクティブにできません.あるいは、フラッシュバックなどの問題が発生します.
この問題は基本的に私を1ヶ月以上悩ませて、ここで感謝します.https://blog.csdn.net/qq_31530015/article/details/52015170ああ、新しい考えがあって、一日でこの問題を解決しました.
 
全体的な考え方.
miniサスペンション+間隔2 sプレビューフレーム+処理(顔検出/画像保存)
 
あまり話さないで、コードをつけてください.
プロジェクトのソースコードの指定:https://github.com/SleepyRae/PhoneSavior
 
Activityでサービスを開始
aSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean f) {
                //        
               // Intent face = new Intent(FaceDetectActivity.this, CameraService.class);
               // Intent face = new Intent(FaceDetectActivity.this, CameraActivity.class);
                Intent face = new Intent(FaceDetectActivity.this, MyService.class);
                if (f) {
                    aSwitch.setSwitchTextAppearance(FaceDetectActivity.this, R.style.s_true);
                    startService(face);
                   // startService(face);
                    ServiceIsOn = true;
                    Toast.makeText(getApplicationContext(), "       ", Toast.LENGTH_SHORT).show();
                } else {
                    aSwitch.setSwitchTextAppearance(FaceDetectActivity.this, R.style.s_false);
                    stopService(face);
                    ServiceIsOn = false;
                    //CameraActivity.finishActivity();
                    Toast.makeText(getApplicationContext(), "       ", Toast.LENGTH_SHORT).show();
                }

            }
        });

 
MyService:
package com.example.inspiron.phonesavior.Service;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.provider.Settings;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public class MyService extends Service {

	/**
	 *      
	 */
	private MyWindow myWindow;
	/**
	 *      
	 */
	private WindowManager mWindowManager;
	/**
	 *       
	 */
	private LayoutParams Params;
 
	private Handler handler = new Handler() {
	public void handleMessage(Message msg) {

			if (isHome()&& myWindow!=null) {
				//       ,      
				if (!myWindow.isAttachedToWindow()) {
					mWindowManager.addView(myWindow, Params);
				}

			} else {
				//       ,      
				/*if (myWindow.isAttachedToWindow()) {
					mWindowManager.removeViewImmediate(myWindow);
				}*/
			}
			super.handleMessage(msg);
		};
	};

	@Override
	public IBinder onBind(Intent arg0) {

		return null;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		Log.d("MyService", "onCreate");
		//     
		Timer timer = new Timer();
		timer.schedule(task, 1000, 1000); // 1s   task,  1s    
		
		//  6.0     
		if (Build.VERSION.SDK_INT >= 23) {
			//         
			if (Settings.canDrawOverlays(getApplicationContext())) {
				 showWindow();
			} else {
				//        
				Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
				intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
				getApplicationContext().startActivity(intent);
			}
		} else {
				//6.0         
				showWindow();
		}

	}

	private void showWindow() {
		//  MyWindow   
		myWindow = new MyWindow(getApplicationContext());
		//     
		mWindowManager = (WindowManager) getSystemService(Service.WINDOW_SERVICE);
		//      
		Params = new WindowManager.LayoutParams();
		//    ,       (0,0)
		Params.x = 0;
		Params.y = 0;

		//    
		Params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; //       ,  

		//  flags
		Params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; //        
		Params.flags = Params.flags | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
		Params.flags = Params.flags | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; //       
		Params.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;

		//   gravity
		Params.gravity = Gravity.LEFT | Gravity.TOP;
 
		//      
		Params.width =  1;
		Params.height = 1;

		myWindow.setOnTouchListener(new OnTouchListener() {
 
			@Override
			public boolean onTouch(View v, MotionEvent event) {
			 	switch (event.getAction()) {				
			 	
			 	case MotionEvent.ACTION_MOVE:
					Params.x = (int) event.getRawX() - myWindow.getWidth() / 2;
					Params.y = (int) event.getRawY() - myWindow.getHeight() / 2;
					//      
					mWindowManager.updateViewLayout(myWindow, Params);
					
					break;
				}
			 	return false;
			}
		 });

	}

	//    message Handler
	TimerTask task = new TimerTask() {
		@Override
		public void run() {
			Message message = new Message();
			handler.sendMessage(message);
		}
	};

	
	/**
	 * @return     (Launcher)   
	 */
	private List getHomes() {
		List names = new ArrayList();
		PackageManager packageManager = this.getPackageManager();
		 
		Intent intent = new Intent(Intent.ACTION_MAIN);
		intent.addCategory(Intent.CATEGORY_HOME);
		List resolveInfo = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
		for (ResolveInfo info : resolveInfo) {
			names.add(info.activityInfo.packageName);
		}
		return names;
	}

	/**
	 * @return          
	 */
	public boolean isHome() {
		ActivityManager mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
		List rti = mActivityManager.getRunningTasks(1);
		List strs = getHomes();
		if (strs != null && strs.size() > 0) {
			return strs.contains(rti.get(0).topActivity.getPackageName());
		} else {
			return false;
		}
	}

    @Override
    public void onDestroy() {
        super.onDestroy();
        myWindow = null;
    }
}

 
MyWindow:
package com.example.inspiron.phonesavior.Service;

import android.app.Service;
import android.content.Context;
import android.graphics.*;
import android.hardware.Camera;
import android.media.FaceDetector;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.Toast;
import com.example.inspiron.phonesavior.R;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class MyWindow extends LinearLayout implements SurfaceTextureListener {

	private TextureView textureView;

	/**
	 *    
	 */
	private Camera myCamera;
	private Context context;

	private WindowManager mWindowManager;
    private int num = 0;
    private int curnum = 0;
    private Bitmap bitmap_get = null;
    private int count = 0;

	public MyWindow(Context context) {
		super(context);
		LayoutInflater.from(context).inflate(R.layout.window, this);
		this.context = context;
		
		initView();
	}

	private void initView() {

		textureView = (TextureView) findViewById(R.id.textureView);
		textureView.setSurfaceTextureListener(this);
		mWindowManager = (WindowManager) context.getSystemService(Service.WINDOW_SERVICE);
	}

	@Override
	public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
		if (myCamera == null) {
			//   Camera  
			//         
			Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
			for (int camIdx = 0, cameraCount = Camera.getNumberOfCameras(); camIdx < cameraCount; camIdx++) {
				Camera.getCameraInfo(camIdx, cameraInfo);
				if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
					try {
						Log.d("Demo", "tryToOpenCamera");
						myCamera = Camera.open(camIdx);
					} catch (RuntimeException e) {
						e.printStackTrace();
					}
				}
			}
			try {
				//      textureView 
				myCamera.setPreviewTexture(surface);
				myCamera.setDisplayOrientation(SetDegree(MyWindow.this));
				//     
				myCamera.startPreview();
                handler.sendEmptyMessage(BUFFERTAG);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

    private void getPreViewImage() {

        if (myCamera != null){
            myCamera.setPreviewCallback(new Camera.PreviewCallback(){

                @Override
                public void onPreviewFrame(byte[] data, Camera camera) {
                    Camera.Size size = camera.getParameters().getPreviewSize();
                    try{
                        YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);
                        if(image!=null){
                            ByteArrayOutputStream stream = new ByteArrayOutputStream();
                            image.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, stream);

                            bitmap_get = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size());

                            //**********************
                            //         ,                    
                            bitmap_get = rotateMyBitmap(bitmap_get);
                            //**********************************

                            stream.close();


                        }
                    }catch(Exception ex){
                        Log.e("Sys","Error:"+ex.getMessage());
                    }
                }


            });
        }


    }

    private void myFace(Bitmap bitmap) {
        bitmap = bitmap.copy(Bitmap.Config.RGB_565, true);
        //     1  
        int MAXfFaces = 1;
        int numOfFaces = 0;
        FaceDetector mFaceDetector = new FaceDetector(bitmap.getWidth(),bitmap.getHeight(),MAXfFaces);
        FaceDetector.Face[] mFace = new FaceDetector.Face[MAXfFaces];
        //          
        numOfFaces = mFaceDetector.findFaces(bitmap, mFace);
        Log.v("------------->",  "pic num:" + num + "  face num:"+numOfFaces +" count:"+count);
        if(numOfFaces == 1 && num!=curnum){
            count++;
            curnum = num;
            Log.d("pic num:" + num,  "  eyesDistance:"+ mFace[0].eyesDistance() +"  confidence:"+ mFace[0].confidence());
        }
    }

    public Bitmap rotateMyBitmap(Bitmap mybmp){
        //*****    
        Matrix matrix = new Matrix();
        matrix.postRotate(270);

        Bitmap bitmap = Bitmap.createBitmap(mybmp.getWidth(), mybmp.getHeight(), Bitmap.Config.ARGB_8888);

        Bitmap nbmp2 = Bitmap.createBitmap(mybmp, 0,0, mybmp.getWidth(),  mybmp.getHeight(), matrix, true);

        saveImage(nbmp2);
        return nbmp2;
    };

    public void saveImage(Bitmap bmp) {
        myFace(bmp);
        /*String fileName ="Camera"+ num +".jpg";
        File file = new File(getExternalStorageDirectory(), fileName);
        try {
            FileOutputStream fos = new FileOutputStream(file);
            bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            fos.flush();
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }*/
    }

    public static final int BUFFERTAG = 100;
    public static final int BUFFERTAG1 = 101;
    private boolean isGetBuffer = true;

    Handler handler = new Handler(){
        public void handleMessage(android.os.Message msg) {
            switch(msg.what){
                case BUFFERTAG:
                    if(count > 60){         //     
                        count = 0;
                        Toast.makeText(context.getApplicationContext(), "        ,     ", Toast.LENGTH_SHORT).show();
                    }
                    if(isGetBuffer){
                        num++;
                        getPreViewImage();
                        handler.sendEmptyMessageDelayed(BUFFERTAG1, 3000);

                    }else{
                        myCamera.setPreviewCallback(null);
                    }
                    break;
                case BUFFERTAG1:
                    myCamera.setPreviewCallback(null);
                    handler.sendEmptyMessageDelayed(BUFFERTAG, 5000);
                    break ;
            }
        };


    };

    Runnable runnable=new Runnable(){
        @Override
        public void run() {
            // TODO Auto-generated method stub  
            //     ,       Runnable  ,                  

            handler.postDelayed(this, 10000);
            Log.d("test", "running!!!");
        }
    };

	private int SetDegree(MyWindow myWindow) { 
		//        
		int rotation = mWindowManager.getDefaultDisplay().getRotation();
		int degree = 0;
		//                       
		switch (rotation) {
		case Surface.ROTATION_0:
			degree = 90;
			break;
		case Surface.ROTATION_90:
			degree = 0;
			break;
		case Surface.ROTATION_180:
			degree = 270;
			break;
		case Surface.ROTATION_270:
			degree = 180;
			break;
		}
		return degree;
	}

	@Override
	public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
		myCamera.stopPreview(); //    
		myCamera.release();     //       
		myCamera = null;

		return false;
	}

	@Override
	public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

	}

	@Override
	public void onSurfaceTextureUpdated(SurfaceTexture surface) {

	}

}

 
コードリファレンス
浮遊窓:https://blog.csdn.net/qq_31530015/article/details/52015170 
プレビューフレームをキャプチャするには:https://blog.csdn.net/u010277233/article/details/52193068