ICS で ACTION_IMAGE_CAPTURE インテントを使用して Droid Razr M の組み込みカメラ アプリを呼び出すのに問題があり、他の誰かがこれを見て、問題を解決/回避する方法を知っていることを望んでいました。私のアプリはカメラを起動し、ユーザーが画像をキャプチャして受け入れるのを待ってから、戻ったときに処理します。ただし、以下のサンプル アプリでは画像の処理が行われておらず、問題が引き続き発生することに注意してください。ここでの重要な要素は、ユーザーが次々と写真を撮り続けることができるように、インテントから戻ったときにすぐにカメラを再度呼び出すことです。これは多くのデバイス (十数個の異なるデバイス) で正常に動作していますが、4.1.2 を実行している Droid Razr M (および以前のバージョンの ICS) では失敗します。2 番目の写真を撮った後、失敗が明らかになりました。カメラのすべてのボタンが無効になり、戻るボタンだけが機能します。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;
}
}
どんな助けでも大歓迎です。