【问题标题】:Droid RAZR M Camera Freezes when invoked via ACTION_IMAGE_CAPTURE Intent通过 ACTION_IMAGE_CAPTURE Intent 调用 Droid RAZR M 相机冻结
【发布时间】:2013-10-17 11:37:40
【问题描述】:

我在我的 Droid Razr M 上使用 ICS 上的 ACTION_IMAGE_CAPTURE Intent 调用内置相机应用程序时遇到问题,我希望其他人已经看到了这一点并知道如何解决/解决该问题。 我的应用程序启动相机,等待用户捕获并接受图像,然后在返回时对其进行处理。但请注意,下面的示例应用程序中没有处理图像,问题仍然存在。这里的关键元素是我们在从 Intent 返回时立即重新调用相机,以允许用户继续拍摄一张张照片。这在许多设备(十几种不同的设备)上运行良好,但在运行 4.1.2(以及早期版本的 ICS)的 Droid Razr M 上失败。拍摄第二张照片后出现故障——相机上的所有按钮都被禁用,只有后退按钮起作用。如果我们在重新启动 Intent 之前在我们的应用程序中延迟 5 秒或更长时间,则不会发生问题——但这是不可接受的。 这是一个演示问题的简单重现应用程序(请注意,您需要启用 WRITE_EXTERNAL_STORAGE 权限才能使其工作):

public class MainActivity extends Activity {

private static final int RESPONSE_SINGLE_SHOT = 45;
private static final String TAG = "CameraTest";

private String mCameraFilePath = null;

@Override
protected void onCreate( Bundle savedInstanceState ) {
    super.onCreate( savedInstanceState );
    setContentView( R.layout.activity_main );
    onLaunchCamera( true );  //The launch is here only for simplification - it also fails in onStart()
}

@Override
protected void onActivityResult( final int requestCode, final int resultCode, final Intent intent )
{
    super.onActivityResult(requestCode, resultCode, intent);
    processImage( requestCode, resultCode, intent );
}

public void onLaunchCamera( boolean fromUserAction )
{
    final String storageState = Environment.getExternalStorageState();
    if (storageState.equals(Environment.MEDIA_MOUNTED))
    {
        final Intent cameraIntent = new Intent( MediaStore.ACTION_IMAGE_CAPTURE );
        cameraIntent.setFlags( Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET );

        final List<ResolveInfo> list = getPackageManager().queryIntentActivities( cameraIntent, 0 );
        //Grab the first camera in the list, this should be the camera app that came with the device:
        final String packageName = list.get(0).activityInfo.packageName;
        final String name = list.get(0).activityInfo.name;

        final File publicDir = Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_DCIM );
        final Time t = new Time();
        t.setToNow();

        File cameraFile = new File( publicDir, "/Camera/" + makePhotoFileName( t )  );
        mCameraFilePath = cameraFile.getAbsolutePath();
        Log.i( TAG, "creating camera file: " +  mCameraFilePath );

        try
        {
            if ( cameraFile.exists() == false )
            {
                cameraFile.getParentFile().mkdirs();
                if ( cameraFile.createNewFile() )
                {
                    cameraIntent.putExtra( MediaStore.EXTRA_OUTPUT, Uri.fromFile( cameraFile ) );
                } else {
                    Log.e( TAG, "failed to create file:" + cameraFile.getAbsolutePath() );
                    return;
                }
            }

        } catch ( IOException e )
        {
            Log.e( TAG, "Could not create file.", e );
            return;
        }

        cameraIntent.setComponent( new ComponentName( packageName, name ) );
        startActivityForResult( cameraIntent, RESPONSE_SINGLE_SHOT );

    } else {
        Log.e(TAG, "SD card not present");
    }
}

private void processImage( final int requestCode, final int resultCode, final Intent intent ) {
    switch (requestCode)
    {
        case RESPONSE_SINGLE_SHOT:
            if ( resultCode == RESULT_OK )
            {       
                runOnUiThread( new Runnable() {
                    @Override
                    public void run() {
                        onLaunchCamera( false );    //Immediately re-run camera
                    }
                });
            }
            else {
                // delete the placeholder file we created
                if ( mCameraFilePath != null ) {
                    final File cameraFile = new File( mCameraFilePath );
                    cameraFile.delete();
                    mCameraFilePath = null;
                }
            }
            break;
        default:
            break;
    }
}

private String makePhotoFileName( final Time t ) {
    final String fileName = t.format("IMG_%Y%m%d_%H%M%S") + ".jpg";
    return fileName;
}
}

非常感谢任何帮助。

【问题讨论】:

  • 你试过异步处理吗?
  • 这可能与这个问题有关吗? stackoverflow.com/questions/18299661/…
  • “但这是不可接受的”——那么您不应该依赖第三方相机应用程序。毕竟,预装和下载的可能有上千个。它们中的任何一个的行为都有些不可预测。
  • 至于“不可接受”——我们想让用户使用设备上的摄像头。默认相机通常具有我们不想从用户手中夺走的高级功能。我们只调用默认相机(参见示例代码)。

标签: android android-intent camera android-4.0-ice-cream-sandwich


【解决方案1】:

我们能够为 Razr M 上的默认摄像头提出的唯一解决方案是在拍摄图像后不要立即返回摄像头。我们通过在 onLaunchCamera() 中的 try-catch 块之前插入以下代码来做到这一点:

if ( !fromUserAction && name.equals( "com.motorola.camera.Camera" ) && Build.MODEL.equals( "XT907" ) )
    return;

这只是一种解决方法,但确实可以防止相机挂起。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多