11

當有人嘗試解鎖我的設備並輸入錯誤的密碼3次時,我想實現通過前置攝像頭捕捉圖像的功能。我檢查了這是可能的Android和一些應用程序也可在市場。使用密碼鎖定設備時捕捉圖像

我已經做了一些工作來實現這一點,但我得到一個黑色的圖像。下面的代碼:

註冊與設備管理員取得廣播不正確的密碼嘗試:

public class DeviceAdminSample extends DeviceAdminReceiver { 

static Context ctx; 

static SharedPreferences getSamplePreferences(Context context) { 

    ctx = context; 

    return context.getSharedPreferences(
      DeviceAdminReceiver.class.getName(), 0); 
} 

@Override 
public void onPasswordFailed(Context context, Intent intent) { 
    super.onPasswordFailed(context, intent); 

    System.out.println("Password Attempt is Failed..."); 

    Intent i = new Intent(context, CameraView.class); 
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
    context.startActivity(i); 

} 

} 

相機類來捕捉圖像,並將其保存到SD卡:

public class CameraView extends Activity implements SurfaceHolder.Callback, 
    OnClickListener { 
private static final String TAG = "CameraTest"; 
Camera mCamera; 
boolean mPreviewRunning = false; 

public void onCreate(Bundle icicle) { 
    super.onCreate(icicle); 
    Log.e(TAG, "onCreate"); 

    setContentView(R.layout.cameraview); 

    mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera); 

    // mSurfaceView.setOnClickListener(this); 

    mSurfaceHolder = mSurfaceView.getHolder(); 
    mSurfaceHolder.addCallback(this); 

    mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    mSurfaceHolder.setKeepScreenOn(true); 

    // mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 

} 

@Override 
protected void onRestoreInstanceState(Bundle savedInstanceState) { 
    super.onRestoreInstanceState(savedInstanceState); 
} 

protected void onResume() { 
    Log.e(TAG, "onResume"); 
    super.onResume(); 
} 

protected void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 
} 

protected void onStop() { 
    Log.e(TAG, "onStop"); 
    super.onStop(); 
} 

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
    Log.e(TAG, "surfaceChanged"); 

    // XXX stopPreview() will crash if preview is not running 
    if (mPreviewRunning) { 
     mCamera.stopPreview(); 
    } 

    Camera.Parameters p = mCamera.getParameters(); 

    mCamera.setParameters(p); 

    mCamera.startPreview(); 
    mPreviewRunning = true; 
    mCamera.takePicture(null, null, mPictureCallback); 


} 

public void surfaceDestroyed(SurfaceHolder holder) { 
    Log.e(TAG, "surfaceDestroyed"); 
    // mCamera.stopPreview(); 
    // mPreviewRunning = false; 
    // mCamera.release(); 

    stopCamera(); 
} 

private SurfaceView mSurfaceView; 
private SurfaceHolder mSurfaceHolder; 

public void onClick(View v) { 
    mCamera.takePicture(null, mPictureCallback, mPictureCallback); 
} 

public void surfaceCreated(SurfaceHolder holder) { 
    Log.e(TAG, "surfaceCreated"); 

    int i = findFrontFacingCamera(); 

    if (i > 0); 
    while (true) { 
     try { 
      this.mCamera = Camera.open(i); 
      try { 
       this.mCamera.setPreviewDisplay(holder); 
       return; 
      } catch (IOException localIOException2) { 
       stopCamera(); 
       return; 
      } 
     } catch (RuntimeException localRuntimeException) { 
      localRuntimeException.printStackTrace(); 
      if (this.mCamera == null) 
       continue; 
      stopCamera(); 
      this.mCamera = Camera.open(i); 
      try { 
       this.mCamera.setPreviewDisplay(holder); 
       Log.d("HiddenEye Plus", "Camera open RE"); 
       return; 
      } catch (IOException localIOException1) { 
       stopCamera(); 
       localIOException1.printStackTrace(); 
       return; 
      } 

     } catch (Exception localException) { 
      if (this.mCamera != null) 
       stopCamera(); 
      localException.printStackTrace(); 
      return; 
     } 
    } 
} 

private void stopCamera() { 
    if (this.mCamera != null) { 
     /*this.mCamera.stopPreview(); 
     this.mCamera.release(); 
     this.mCamera = null;*/ 
     this.mPreviewRunning = false; 
    } 
} 

private int findFrontFacingCamera() { 
    int i = Camera.getNumberOfCameras(); 
    for (int j = 0;; j++) { 
     if (j >= i) 
      return -1; 
     Camera.CameraInfo localCameraInfo = new Camera.CameraInfo(); 
     Camera.getCameraInfo(j, localCameraInfo); 
     if (localCameraInfo.facing == 1) 
      return j; 
    } 
} 

Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() { 

    public void onPictureTaken(byte[] data, Camera camera) { 
     if (data != null) { 
      // Intent mIntent = new Intent(); 
      // mIntent.putExtra("image",imageData); 

      mCamera.stopPreview(); 
      mPreviewRunning = false; 
      mCamera.release(); 

      try { 
       BitmapFactory.Options opts = new BitmapFactory.Options(); 
       Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, 
         data.length, opts); 
       bitmap = Bitmap.createScaledBitmap(bitmap, 300, 300, false); 
       int width = bitmap.getWidth(); 
       int height = bitmap.getHeight(); 
       int newWidth = 300; 
       int newHeight = 300; 

       // calculate the scale - in this case = 0.4f 
       float scaleWidth = ((float) newWidth)/width; 
       float scaleHeight = ((float) newHeight)/height; 

       // createa matrix for the manipulation 
       Matrix matrix = new Matrix(); 
       // resize the bit map 
       matrix.postScale(scaleWidth, scaleHeight); 
       // rotate the Bitmap 
       matrix.postRotate(-90); 
       Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, 
         width, height, matrix, true); 

       ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 
       resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 40, 
         bytes); 

       // you can create a new file name "test.jpg" in sdcard 
       // folder. 
       File f = new File(Environment.getExternalStorageDirectory() 
         + File.separator + "test.jpg"); 

       System.out.println("File F : " + f); 

       f.createNewFile(); 
       // write the bytes in file 
       FileOutputStream fo = new FileOutputStream(f); 
       fo.write(bytes.toByteArray()); 

       // remember close de FileOutput 
       fo.close(); 

      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
      // StoreByteImage(mContext, imageData, 50,"ImageName"); 
      // setResult(FOTO_MODE, mIntent); 
      setResult(585); 
      finish(); 
     } 
    } 
}; 
} 
+0

手機解鎖後,您是否測試了代碼? – 2013-04-22 16:33:38

+0

是的,我可以使用此代碼在手機解鎖時捕獲圖像... – 2013-04-23 04:55:38

+0

@KrishnakantDalal:您是否檢查了Android控制檯日誌。有沒有錯誤信息? – 2013-04-23 17:45:11

回答

6

我測試了你的代碼,我得到了一個合適的圖像,所以我認爲你的相機代碼工作正常。

您可以查看我的代碼here。 我複製了你的CameraView類。 我從https://github.com/marakana/DevicePolicyDemo 拍攝的設備管理部分第一次嘗試失敗時拍攝照片。

我懷疑它可能是某種硬件問題。 我不確定你是否看過Taking picture from camera without preview

第二個答案提到,使用虛擬SurfaceView僞造預覽不適用於所有Android設備。請參閱他的blog。他在各種手機上做了測試。 你可以試試我的項目,如果它不能在你的手機上工作。這可能是這種情況。 (其他答案也可能對你有用。)

我在CM10的Galaxy S3上試過我的代碼。

希望這會有所幫助。編輯1:測試HTC One,HTC One X,索尼Experia。工作正常。

編輯2:在Galaxy Note上工作。

+0

非常感謝...它真的很有幫助。我第一次在三星Nexus上進行測試,但後來我在其他設備上進行了測試,除了三星Nexus之外,它正在開發所有這些功能。我測試了LG Nexus,三星Galaxy Tab 7'和10',三星SII和三星SII上的應用程序。再次感謝大家親愛的...... – 2013-04-26 19:55:35

+0

歡迎您 – pt2121 2013-04-26 20:22:05

+0

請幫我個忙,如果您在其他設備上測試此代碼,請在此處更新,以確保我的應用程序支持多個設備。 – 2013-04-30 05:12:16

0

我不確定這可以在其他設備上工作,但如果這樣做,它可能會提供一些洞察發生的事情。

在Camera.Parameters中,有一個功能可以將原始拜爾圖像直接保存到SD卡上。該圖像在創建.jpeg文件之前發生,因此如果操作系統將圖像清空,則此圖像可能不受影響。

Camera.Parameters parameters=camera.getParameters(); 
    parameters.set("rawsave-mode", "1"); 
    parameters.set("rawfname", "/mnt/sdcard2/test5.raw"); 
    camera.setParameters(parameters); 

如果該功能您的設備上工作,你應該能夠確定拍攝圖像最好和消滅,或者如果它不採取在所有。

如果原始圖像有效,將bayer轉換爲RGB圖像或灰度圖像相當容易。

我會看到的其他領域是logcat信息並比較代碼的未鎖定上下文和代碼的鎖定上下文之間的日誌。如果存在安全問題,它應該反映在logcat中。