在设备被密码锁定时捕获图像
Posted
技术标签:
【中文标题】在设备被密码锁定时捕获图像【英文标题】:Capture Image while Device is Locked with Password 【发布时间】:2013-04-11 03:23:30 【问题描述】:我想实现一个功能,当有人试图解锁我的设备并输入错误密码 3 次时,通过前置摄像头捕获图像。我检查了它在 android 中是可行的,并且某些应用程序也可以在 Market 中使用。
我已经做了一些工作来实现这一点,但我得到了一个黑色图像。这是代码:
向设备管理员注册以获取错误密码尝试的广播:
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);
Camera 类捕捉图像并将其保存到 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();
;
【问题讨论】:
你在手机解锁时测试过代码吗? 是的,我可以在手机解锁时使用此代码捕获图像... @KrishnakantDalal:你检查过 Android 控制台日志吗?是否有任何错误消息? @KrishnakantDalal:还有一个想法。您可以对 Lookout 应用程序进行逆向工程,看看它是如何做到的 (usatoday.com/story/tech/columnist/baig/2013/01/22/…)。免责声明:检查它在您所在的国家/地区是否合法。这个想法不鼓励任何非法活动:) 我试过你的代码,如果用户输入错误的密码 5 次,它不会捕获图像,但是如果你能够在错误的密码上捕获图像,那么通过参数解锁设备并开始你的活动来捕获图像(可以很好地捕获图像并将正确的图像存储在 sdcard 上),一旦捕获,再次以参数方式锁定设备。可以帮助你。 【参考方案1】:我已经测试了您的代码,并且得到了正确的图像,因此我认为您的相机代码可以正常工作。
您可以查看我的代码here。 我从你那里复制了 CameraView 类。 我从https://github.com/marakana/DevicePolicyDemo 获取的设备管理部分 第一次尝试失败时拍摄的照片。
我怀疑这可能是某种硬件问题。 我不确定你是否见过Taking picture from camera without preview。
那里的第二个答案提到使用虚拟 SurfaceView 伪造预览不适用于所有 Android 设备。请参阅他的blog。他在各种手机上完成了测试。 你可以试试我的项目,如果它在你的手机上不起作用。可能是这种情况。 (其他答案也可能对您有用。)
我在带有 CM10 的 Galaxy S3 上尝试了我的代码。
希望这会有所帮助。
Edit1:在 HTC One、HTC One X、Sony Experia 上测试。工作正常。
Edit2:在 Galaxy Note 上工作。
【讨论】:
非常感谢...它真的很有帮助。我首先在三星 Nexus 上进行了测试,但后来我在许多其他设备上进行了测试,除了三星 Nexus 之外,它正在处理所有这些。我在 LG Nexus、三星 Galaxy Tab 7' 和 10'、三星 SII 和三星 SII 上测试了该应用程序。再次感谢亲爱的.... 请帮我一个忙,如果您也在其他设备上测试此代码,请在此处继续更新,以便我确定我的应用程序支持设备数量。 当然,我会的。几天前我在 Galaxy Note 上进行了测试。工作正常。【参考方案2】:我不确定这是否适用于其他设备,但如果可以,它可能会提供一些关于正在发生的事情的见解。
在Camera.Parameters中,有一个功能可以将原始拜耳图像直接保存到SD卡中。此图像发生在 .jpeg 文件创建之前,因此如果操作系统正在清除图像,则此图像可能不会受到影响。
Camera.Parameters parameters=camera.getParameters(); parameters.set("rawsave-mode", "1"); parameters.set("rawfname", "/mnt/sdcard2/test5.raw"); camera.setParameters(parameters);
如果此功能在您的设备上可用,您应该能够确定照片是正在拍摄并被清除,还是根本没有拍摄。
如果原始图像有效,则将拜耳图像转换为 RGB 图像或灰度图像相当容易。
我要查看的另一个领域是 logcat 信息,并比较未锁定的代码上下文和锁定的代码上下文之间的日志。如果有安全问题,应该反映在logcat中。
【讨论】:
以上是关于在设备被密码锁定时捕获图像的主要内容,如果未能解决你的问题,请参考以下文章