web-dev-qa-db-ja.com

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

Android.hardware.Cameraが非推奨であり、変数Cameraを使用できない場合、これに代わるものは何ですか?

85
raja121

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;
    }
}

これにより、一方から他方への切り替えと、両方の実装を処理できるコードの作成が難しくなります。

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

1つ離れて

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

ここでは、そのインターフェイスと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を使用しない場合は、ユーティリティを作成するか、Factoryパターンを使用して適切なものを作成できます。重要な部分は、APIレベルがチェックされることです。

93
user4469467

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

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

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

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

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

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

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

5
Robert Sherman

Android.hardware.Cameraが非推奨になったため、Android.hardware.camera2を使用する必要があります。これは、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;
                    }


            }
        });
    }
}

どのカメラ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
Oguz Ozcan