Search code examples
androidandroid-activityandroid-preferencesandroid-camera2android-viewmodel

How to get CameraManager in ViewModel without holding reference to my activity/context?


In my app I am using the Android Jetpack as well as the Navigation Architecture Component. So now I wanted to add my settings fragment with multiple setting fragments. The navigation so far works fine and there is no problem - now I got a camera setting fragment where the user can do some settings about the camera. The thing is that I now wanted to fill a ListPreference with possible resolutions that the device camera provides. So all my setting fragments shall use my one SettingsViewModel to hold data whatever. I thought I could make a method in my SettingsViewModel to get those resolutions, but I don't know how to get the CameraManager without violating a reference to my activity.

MainActivity.java

    public class MainActivity extends AppCompatActivity implements
        NavigationView.OnNavigationItemSelectedListener,
        ActivityCompat.OnRequestPermissionsResultCallback,
        PreferenceFragmentCompat.OnPreferenceStartFragmentCallback{

...

    @Override
    public boolean onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref) {

        switch (pref.getTitle().toString()){
            case "Camera":
                Log.i(TAG, "camera settings selected");

                navController.navigate(R.id.cameraSettingFragment);

                }
        return true;
    }

CameraSettingFragment.java

    public class CameraSettingFragment extends PreferenceFragmentCompat {

    private static final String TAG = "CameraSettingFragment";

    private SettingsViewModel mViewModel;

    @Override
    public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
        setPreferencesFromResource(R.xml.camera_preferences, rootKey);

        mViewModel = ViewModelProviders.of(this).get(SettingsViewModel.class);

        setupCameraPreferences();

    }

    private void setupCameraPreferences() {

        getPossibleFrameRateRanges();

        getPossibleCameraResolutions();

    }



    private void getPossibleFrameRateRanges(){

        final ListPreference listPreference = findPreference("framerate");

        CharSequence[] entries = listPreference.getEntries();

        if(entries == null){

            mViewModel.getPossibleFrameRateRanges();

        }

And my ViewModel where I wanted to do some stuff about camera characteristics

    import static android.content.Context.CAMERA_SERVICE;

    public class SettingsViewModel extends AndroidViewModel {

    public SettingsViewModel(@NonNull Application application) {
        super(application);
    }

    public void doAction() {
        // depending on the action, do necessary business logic calls
    }

    public void getPossibleFrameRateRanges() {
        // THIS LINE IS BUGGY AND NEEDS A FIX
        CameraManager manager = (CameraManager) getSystemService(CAMERA_SERVICE);
    }
}

So how do I not violate those lines:

Caution: A ViewModel must never reference a view, Lifecycle, or any class that may hold a reference to the activity context.

Or am I missing something? Thanks in advance!


Solution

  • Sorry to steal your time! I have not read enough... I can like I did extend my SettingsViewModel class with the AndroidViewModel and use application

        public class SettingsViewModel extends AndroidViewModel {
    
        private Application application;
    
        public SettingsViewModel(@NonNull Application application) {
            super(application);
            this.application = application;
        }
    
        public void doAction() {
            // depending on the action, do necessary business logic calls
        }
    
        public void getPossibleFrameRateRanges() {
    
            CameraManager manager = (CameraManager) application.getSystemService(CAMERA_SERVICE);
        }
    }
    

    So sorry and thank you!