Androidカメラandroid.hardware.Cameraは非推奨


97

場合はandroid.hardware.Camera廃止され、あなたは変数を使用することはできませんCamera、そして、何がこれに代わるだろうか?



1
私はアプリでこの問題を抱えていて、これは非常に役に立ちました。インテントを使用する場合、制限されます。:このチュートリアルでは、代替説明してdeveloper.android.com/guide/topics/media/...
ロナウドバイア

回答:


102

APIドキュメント

よると、Androidの開発者ガイドのためandroid.hardware.Camera、彼らは状態:

新しいアプリケーションには、新しいandroid.hardware.camera2 APIを使用することをお勧めします。

android.hardware.camera2(上記のリンク)に関する情報ページには、次のように記載されています。

android.hardware.camera2パッケージは、Androidデバイスに接続された個々のカメラデバイスへのインターフェイスを提供します。廃止されたCameraクラスを置き換えます。

問題

そのドキュメントを確認すると、これらの2つのカメラAPIの実装が非常に異なっていることがわかります。

たとえば、カメラの向きを取得する android.hardware.camera

@Override
public int getOrientation(final int cameraId) {
    Camera.CameraInfo info = new Camera.CameraInfo();
    Camera.getCameraInfo(cameraId, info);
    return info.orientation;
}

android.hardware.camera2

@Override
public int getOrientation(final int cameraId) {
    try {
        CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
        String[] cameraIds = manager.getCameraIdList();
        CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraIds[cameraId]);
        return characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
    } catch (CameraAccessException e) {
        // TODO handle error properly or pass it on
        return 0;
    }
}

これにより、1つのスイッチから別のスイッチに切り替えたり、両方の実装を処理できるコードを記述したりすることが難しくなります。

この単一のコード例では、古いカメラAPI intがカメラIDのプリミティブで動作する一方で、新しいカメラAPI がStringオブジェクトで動作するという事実を回避する必要があったことに注意してください。この例では、新しいAPIでインデックスとしてintを使用することで、それをすばやく修正しました。カメラが返される順序が常に同じとは限らない場合は、既に問題が発生しています。別のアプローチは、おそらく安全な古いint cameraIDのStringオブジェクトとString表現を操作することです。

一周

この大きな違いを回避するために、最初にインターフェースを実装し、コードでそのインターフェースを参照できます。

ここでは、そのインターフェースと2つの実装のコードをいくつかリストします。実際のカメラAPIの使用に実装を制限して、作業量を制限できます。

次のセクションでは、これらをロードする方法を簡単に説明します。

この例を制限するために必要なすべてをラッピングするインターフェイス。ここには2つのメソッドしかありません。

public interface CameraSupport {
    CameraSupport open(int cameraId);
    int getOrientation(int cameraId);
}

これで、古いカメラハードウェアAPIのクラスができました。

@SuppressWarnings("deprecation")
public class CameraOld implements CameraSupport {

    private Camera camera;

    @Override
    public CameraSupport open(final int cameraId) {
        this.camera = Camera.open(cameraId);
        return this;
    }

    @Override
    public int getOrientation(final int cameraId) {
       Camera.CameraInfo info = new Camera.CameraInfo();
       Camera.getCameraInfo(cameraId, info);
       return info.orientation;
    }
}

そして、新しいハードウェアAPIのもう1つ:

public class CameraNew implements CameraSupport {

    private CameraDevice camera;
    private CameraManager manager;

    public CameraNew(final Context context) {
        this.manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
    }

    @Override
    public CameraSupport open(final int cameraId) {
        try {
            String[] cameraIds = manager.getCameraIdList();
            manager.openCamera(cameraIds[cameraId], new CameraDevice.StateCallback() {
                @Override
                public void onOpened(CameraDevice camera) {
                    CameraNew.this.camera = camera;
                }

                @Override
                public void onDisconnected(CameraDevice camera) {
                    CameraNew.this.camera = camera;
                    // TODO handle
                }

                @Override
                public void onError(CameraDevice camera, int error) {
                    CameraNew.this.camera = camera;
                    // TODO handle
                }
            }, null);
        } catch (Exception e) {
            // TODO handle
        }
        return this;
    }

    @Override
    public int getOrientation(final int cameraId) {
        try {
            String[] cameraIds = manager.getCameraIdList();
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraIds[cameraId]);
            return characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
        } catch (CameraAccessException e) {
            // TODO handle
            return 0;
        }
    }
}

適切なAPIをロードする

CameraOldまたはCameraNewクラスをロードするにCameraNewは、APIレベル21からしか使用できないため、APIレベルを確認する必要があります。

依存関係注入がすでに設定されている場合は、CameraSupport実装を提供するときにモジュールで設定できます。例:

@Module public class CameraModule {

    @Provides
    CameraSupport provideCameraSupport(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            return new CameraNew(context);
        } else {
            return new CameraOld();
        }
    } 
}

DIを使用しない場合は、ユーティリティを作成するか、ファクトリパターンを使用して適切なユーティリティを作成できます。重要な部分は、APIレベルがチェックされることです。


25
21未満のAndroid APIレベルをサポートする必要がある場合はどうなりますか?
niveuseverto 2015

1
@Angeliusこのドキュメントは、おそらくdeveloper.android.com/guide/topics/media/camera.htmlの助けになるでしょう -しかし、それは別の質問であるか、非推奨の変数を使用する必要があるかどうかに関する質問を検索できます。

@Angeliusここに関するいくつかの情報があり@SuppressWarnings、このQAのでstackoverflow.com/questions/7397996/...

5
@deprecatedクラスを使用するだけでなく、下位互換性のあるアプリを作成する方法を考えていますか?これに関する公式のヘルプ?私はこれについて考えています。ICameraインターフェイス。現在の電話バージョンに対応するCameraオブジェクトでサポートされていますが、これは少し単純で、維持するのが困難です...
niveuseverto

@Angeliusあなたが説明しているものは別の質問である可能性があります(最初に質問されたかどうかを確認してください)。

5

同じ問題に直面し、非推奨のカメラAPIを介して古いデバイスをサポートし、現在のデバイスと将来の両方のデバイスに新しいCamera2 APIが必要です。私は同じ問題に遭遇しました- おそらく2つのAPIを橋渡しするサードパーティのライブラリを見つけられませんでした。恐らく、APIが非常に異なるため、基本的なOOPプリンシパルに目を向けました

2つのAPIは著しく異なっており、古いAPIで提供されているインターフェースを想定しているクライアントオブジェクトにとって、2つのAPIを交換すると問題が生じます。新しいAPIには、異なるアーキテクチャを使用して構築された、異なるメソッドを持つ異なるオブジェクトがあります。グーグルが大好きになりましたが、ラグナビット!それはイライラします。

そこで、アプリに必要なカメラ機能のみに焦点を当てたインターフェイスを作成し、そのインターフェイスを実装する両方の APIの単純なラッパーを作成しました。そうすれば、私のカメラアクティビティは、どのプラットフォームで実行されているかを気にする必要がなくなります...

また、APIを管理するためにシングルトンをセットアップしました。古いAPIのラッパーを古いAndroid OSデバイス用のインターフェースでインスタンス化し、新しいAPIのラッパークラスを新しいAPIを使用する新しいデバイス用にインスタンス化します。シングルトンには、APIレベルを取得して適切なオブジェクトをインスタンス化するための典型的なコードがあります。

両方のラッパークラス同じインターフェイスが使用されるため、アプリがJellybeanとMarshmallowのどちらで実行されているかは関係ありません。インターフェイスが同じメソッドシグネチャを使用して、どちらかのCamera APIから必要なものをアプリに提供する限り、カメラは、Androidの新旧両方のバージョンで同じようにアプリで実行されます。

シングルトンは、APIに関連付けられていない関連することもいくつか実行できます。たとえば、デバイスに実際にカメラがあることを検出したり、メディアライブラリに保存したりできます。

このアイデアがお役に立てば幸いです。


例えば:public interface AllCameraInterface { void open(); boolean setDirection(); Bitmap preview(); Bitmap takePhoto(); void close(); }
ロバート・シャーマン

例:public interface AllCameraInterface { void open(); Bitmap takePhoto(); void close(); etc... } public class NCamera implements AllCameraInterface... public class OCamera implements AllCameraInterface... public class AllCamera { private static AllCamera ourInstance = new AllCamera(); public static AllCamera getInstance() {...} private AllCameraInterface camera; private AllCamera() { if (android.os.Build.VERSION.SDK_INT <= 20) { camera = new OCamera(); } else { camera = new NCamera(); } }それを返すメソッド...
Robert Sherman

どうやらコメントでは改行は許されません;-)しかし、それは本当に機能します
Robert Sherman

4
コメントのコードを回答に直接追加してみませんか?
エンジェルコー

@RobertShermanこんにちはロバート、新しい小さなスニペットを書き直すのを手伝ってくれませんcamera2か?私は本当に混乱しています...私はちょうど必要とするenableAutofocus:カメラを開き、フォーカスを設定する方法をstackoverflow.com/questions/19076316/...

0

次に、android.hardware.camera2を使用する必要があります。android.hardware.Cameraは非推奨であり、API> 23 FlashLightでのみ機能します。

   public class MainActivity extends AppCompatActivity {

     Button button;

     Boolean light=true;

     CameraDevice cameraDevice;

     private CameraManager cameraManager;

     private CameraCharacteristics cameraCharacteristics;

     String cameraId;

     @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button=(Button)findViewById(R.id.button);
        cameraManager = (CameraManager) 
        getSystemService(Context.CAMERA_SERVICE);
        try {
          cameraId = cameraManager.getCameraIdList()[0];
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(light){
                    try {

                        cameraManager.setTorchMode(cameraId,true);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }

                    light=false;}
                    else {

                    try {

                      cameraManager.setTorchMode(cameraId,false);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }


                    light=true;
                    }


            }
        });
    }
}

0

使用するカメラAPIとしてここに記載されている回答は間違っています。または、彼らは不十分であると言う方が良いでしょう。

一部の電話(Samsung Galaxy S6など)は、APIレベル21を超える可能性がありますが、それでもCamera2 APIをサポートしていない場合があります。

CameraCharacteristics mCameraCharacteristics = mCameraManager.getCameraCharacteristics(mCameraId);
Integer level = mCameraCharacteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
if (level == null || level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
    return false;
}

Camera2ApiのCameraManagerクラスには、カメラの特性を読み取るメソッドがあります。ハードウェアワイズデバイスがCamera2 Apiをサポートしているかどうかを確認する必要があります。

ただし、深刻なアプリケーションで実際に機能させたい場合は、さらに処理する必要のある問題があります。たとえば、一部のデバイスでは自動フラッシュオプションが機能しないか、電話のバッテリーレベルがカメラにRuntimeExceptionを作成するか、電話が無効を返す可能性があります。カメラIDなど

したがって、最善のアプローチは、フォールバックメカニズムを使用することです。何らかの理由でCamera2が起動に失敗した場合、Camera1を試すことができます。失敗した場合も、Androidを呼び出してデフォルトのカメラを開くことができます。


0
 if ( getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) {

          CameraManager cameraManager=(CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);


           try {
               String cameraId = cameraManager.getCameraIdList()[0];
               cameraManager.setTorchMode(cameraId,true);
           } catch (CameraAccessException e) {
               e.printStackTrace();
           }


 }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.