2016-07-10 1 views
1

firebase storageサンプルアプリケーションを使用してstorage appをビルドしようとしましたが、写真を撮るときに常にonActivityResult(..)でRESUL_CANCELEDを取得します。写真を撮ると、常にonActivityResult(..)のRESULT_CANCELED(0)が返されます。

@AfterPermissionGranted(RC_STORAGE_PERMS) 
private void launchCamera() { 
    Log.d(LOG_TAG, "launchCamera"); 

    // Check that we have permission to read images from external storage. 
    String perm = Manifest.permission.WRITE_EXTERNAL_STORAGE; 
    if (!EasyPermissions.hasPermissions(this, perm)) { 
     EasyPermissions.requestPermissions(this, getString(R.string.rationale_storage), 
       RC_STORAGE_PERMS, perm); 
     return; 
    } 

    // Choose file storage location, must be listed in res/xml/file_paths.xml 
    File externalDir = Environment.getExternalStorageDirectory(); 
    File file = new File(externalDir, "photos/" + UUID.randomUUID().toString() + ".jpg"); 

    // Create content:// URI for file, required since Android N 
    // See: https://developer.android.com/reference/android/support/v4/content/FileProvider.html 
    mFileUri = FileProvider.getUriForFile(this, 
      "com.google.firebase.quickstart.firebasestorage.fileprovider", file); 

    // Create and launch the intent 
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mFileUri); 

    startActivityForResult(takePictureIntent, RC_TAKE_PICTURE); 
} 

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
    Log.d(LOG_TAG, "onActivityResult:" + requestCode + ":" + resultCode + ":" + data); 
    if (requestCode == RC_TAKE_PICTURE) { 
     if (resultCode == RESULT_OK) { 
      if (mFileUri != null) { 
       uploadFromUri(mFileUri); 
      } else { 
       Log.w(LOG_TAG, "File URI is null"); 
      } 
     } else { 
      Toast.makeText(this, "Taking picture failed.", Toast.LENGTH_SHORT).show(); 
     } 
    } 
} 

ログ:onActivityResult:101:0:インテント{}

+0

別のカメラアプリをお試しください。 'ACTION_IMAGE_CAPTURE'実装には[バグの履歴](https://commonsware.com/blog/2015/06/08/action-image-capture-fallacy.html)があります。また、保存したインスタンスの状態 'Bundle'に' mFileUri'を入れることを忘れないでください。カメラアプリがフォアグラウンドにある間にプロセスが終了する可能性があるからです。 – CommonsWare

+0

@CommonsWareありがとう、それは問題でした。だからそれはAndroidのバージョンによりますか? – madim

答えて

6

だからそれは、Androidのバージョンから依存ここ コードですか?

これは、その意味とバグの内容によって異なります。

私のコメントで指摘したように、ACTION_IMAGE_CAPTUREの実装はa history of bugsです。このようなバグは広範囲にあり、必ずしもAndroid OSのバージョンには関係しません。

ただし、EXTRA_OUTPUTには面白いアプローチが使用されています。FileProviderを外部ストレージの場所に使用してください。長期的には、FileProviderはいい答えです。Android N is starting to ban file:Uri valuesです。しかし、content:Uriの値で問題になるカメラアプリがたくさんあります。なぜなら、それらのカメラアプリの開発者はそのような値を期待していなかったからです。たとえば、ACTION_IMAGE_CAPTUREでも問題はありませんが、Googleの独自のカメラアプリは、ACTION_VIDEO_CAPTUREcontent:Uriの値になりました。

さらに悪いことに、アプリが余分にサポートしているスキームを広告する方法はありません。 Intentの "データ"ファセットでは、<intent-filter>はサポートされているスキームを宣伝することができますが、それは特別な場合には機能しません。したがって、content:UriEXTRA_OUTPUTACTION_IMAGE_CAPTUREを呼び出すと、content:Uri値をサポートするカメラアプリに限定されません。

一時的にtargetSdkVersionを削除してから、FileProvider.getUriForFile(...)の代わりにUri.fromFile(file)を使用して、何が起こるかを確認することがあります。オリジナルのカメラアプリが正常に動作している場合、そのアプリはcontent:Uriの値を正しくサポートしていないため、元の問題の原因となっていました。

全体的に、私は彼らのtargetSdkVersion 24の下を維持し、数年のためのfile:Uri値を使用ACTION_IMAGE_CAPTUREを使用して、開発者は、利用者の割合が高いような時間まで、カメラアプリは、それがcontent:Uri値をサポートしていますインストールされていることをお勧めします。または、ユーザーに既存のカメラアプリ(ACTION_IMAGE_CAPTURE経由)と自分のアプリに組み込むカメラ機能(たとえばmy libraryを使用)のどちらかを選択して、の何かがとなる確率を上げることができます。

0

@CommonsWareに追加するスムーズな回避策を呼び出すコードを追加するだけです。 APIをチェックして適切に処理すると効果的です。

private void startCamera() { 
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 

    if (takePictureIntent.resolveActivity(getPackageManager()) != null) { 
     File photoFile = null; 
     try { 
      photoFile = ImgUtils.createTempImageFile(this); 
     } catch (IOException ex) { 
      ex.printStackTrace(); 
     } 
     if (photoFile != null) { 
      mTempPhotoPath = photoFile.getAbsolutePath(); 
      if(Build.VERSION.SDK_INT < 24) { 

      //create Uri with 'file://' prefix 
       tempImgUri = Uri.fromFile(photoFile); 
      }else{ 

      //create Uri with 'content://' prefix 
       tempImgUri = FileProvider.getUriForFile(this, 
         FILE_PROVIDER_AUTHORITY, 
         photoFile); 
      } 
      mImgUriString = tempImgUri.toString(); 

      // Add the URI so the camera can store the image 
      takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, tempImgUri); 
      startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE); 
     } 
    } 
関連する問題