Android O:设备锁定时拍照

时间:2018-10-12 12:42:37

标签: android android-camera android-8.0-oreo

我正在开发一个应用,该应用可以拍摄试图以错误的密码或图案解锁设备的人的照片。

该应用使用DeviceAdminReceiver.onPasswordFailed()例程检测失败的尝试。一切都可以在所有版本的Android上正常运行,除非我在Android O真实设备上使用它(在模拟器上运行正常)。

这是我的代码:

public class AdminReceiver extends DeviceAdminReceiver {
    @Override
    public void onPasswordFailed(Context context, Intent intent) {
       super.onPasswordFailed(context, intent);
       Intent i = new Intent(context, CameraActivity.class);
       i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
       context.startActivity(i);
 }

拍照的代码是在透明的活动中进行的:

public class CameraActivity extends AppCompatActivity {

   private static final String TAG = CameraActivity.class.getSimpleName();

   private Camera mCamera;
   private boolean executed = false;

   private CameraPreview.CamCallback camCallback = (data, camera) -> {

      //used to prevent picture from being captured twice, because apparently
      // Camera.stopPreview() takes sometime to execute
      if (!executed) {
         executed = true;
         log.d(TAG, "CameraActivity camCallback executed");
         Camera.Parameters params = camera.getParameters();
         Camera.Size size = params.getPreviewSize();
         camera.stopPreview();

         File dir = new File(STORE_DIRECTORY);
         if (!(dir.exists() || dir.mkdirs())) {
            Log.e(TAG, "Failed to create file storage directory.");
            return;
         }
         String imgname = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss",
                                   Locale.getDefault()).format(new Date());
         File file = new File(dir, imgname + ".jpg");

         OutputStream fOut;
         try {
            if (file.exists() && !file.delete()) {
               Log.e(TAG, "File already exists and could not be deleted!");
               finish();
               return;
            }

            if (!file.exists() && !file.createNewFile()) {
               Log.e(TAG, "failed to create image file.");
               finish();
               return;
            }

            fOut = new FileOutputStream(file);
            YuvImage yuvImage = new YuvImage(data, params.getPreviewFormat(),
                                             size.width, size.height, null);
            processImage(yuvImage, fOut);
            fOut.flush();
            fOut.close();
         } catch (FileNotFoundException e) {
            Log.e(TAG, "Output file not found!");
            e.printStackTrace();
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
      finish();
   };

   private void processImage(@NotNull YuvImage yuvImage, OutputStream fOut) {
       ByteArrayOutputStream os = new ByteArrayOutputStream();
       yuvImage.compressToJpeg(new Rect(0, 0, yuvImage.getWidth(), yuvImage.getHeight()),90, os);

       byte[] bytes = os.toByteArray();
       Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
       Matrix matrix = new Matrix();
       matrix.postRotate(bitmap.getWidth() > bitmap.getHeight() ? -90.0f : 0.0f);
       Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true)
        .compress(Bitmap.CompressFormat.JPEG, 100, fOut);
  }

  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
      log.i(TAG, "CameraActivity->onCreate");
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_camera);

      getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
            | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
            | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
            | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);

      // Setup the camera and the preview object
      int frontCamIndex = findFrontFacingCamera();

      if (frontCamIndex == -1) {
          Log.e(TAG, "findFrontFacingCamera: ",
               new IOException("No facing Camera detected on this device"));
          finish();
          return;
      }

      mCamera = Camera.open(frontCamIndex);
      CameraPreview camPreview = new CameraPreview(this, mCamera, camCallback);
      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 = findViewById(R.id.cameraView);
      preview.addView(camPreview);

      // Attach a callback for preview
      mCamera.setPreviewCallback(camCallback);
   }

   @Override
   protected void onDestroy() {
       super.onDestroy();
       Logger.log("CameraActivity->onDestroy");
       if (mCamera != null)
           mCamera.release();
    }
 }
清单中的

CameraActivity

    <activity
        android:name=".activities.CameraActivity"
        android:showWhenLocked="true"
        android:theme="@style/Theme.Transparent" />

CameraActivity的样式:

 <style name="Theme.Transparent" parent="android:Theme">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowIsFloating">true</item>
    <item name="android:backgroundDimEnabled">false</item>
 </style>

还有带有CameraPreview接口的CamCallback类:

public class CameraPreview extends TextureView implements TextureView.SurfaceTextureListener {

   public interface CamCallback extends Camera.PreviewCallback {
      void onPreviewFrame(byte[] data, Camera camera);
   }

   private Camera mCamera;
   private CamCallback callback;

   public CameraPreview(Context context) {
      super(context);
   }

   public CameraPreview(Context context, Camera camera, CamCallback callback) {
      super(context);
      mCamera = camera;
      this.callback = callback;
   }

   @Override
   public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
      Camera.Parameters params = mCamera.getParameters();

      try {
         mCamera.setPreviewTexture(surface);
      } catch (IOException t) {
         t.printStackTrace();
      }

      Camera.Size size = getBiggestPictureSize();
      setLayoutParams(new FrameLayout.LayoutParams(size.width, size.height, Gravity.CENTER));
      params.setPreviewSize(size.width, size.height);
      mCamera.setParameters(params);
      mCamera.setPreviewCallback(callback);
      try {
         mCamera.setPreviewTexture(surface);
      } catch (IOException e) {
         e.printStackTrace();
      }
      mCamera.startPreview();
      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

      try {
         mCamera.stopPreview();
         mCamera.setPreviewCallback(callback);
         try {
            mCamera.setPreviewTexture(surface);
         } catch (IOException e) {
            e.printStackTrace();
         }
         mCamera.startPreview();
      } catch (Exception ex) {
         ex.printStackTrace();
      }
   }

   @Override
   public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
      return true;
   }

   @Override
   public void onSurfaceTextureUpdated(SurfaceTexture surface) {
      // Update your view here!
   }

   private Camera.Size getBiggestPictureSize() {
      Camera.Size result = null;

      for (Camera.Size size : mCamera.getParameters().getSupportedPictureSizes()) {
         if (result == null) {
            result = size;
         } else {
            int resultArea = result.width * result.height;
            int newArea = size.width * size.height;

            if (newArea > resultArea) {
               result = size;
            }
         }
      }

      return (result);
   }
}

正在创建CameraActivity,因为我可以在logcat中看到它,并且logcat完全没有显示错误。

0 个答案:

没有答案