Getting started with AndroidLayoutsGradle for AndroidRecyclerView onClickListenersNavigationViewIntentJSON in Android with org.jsonAndroid StudioResourcesData Binding LibraryExceptionsGetting Calculated View DimensionsAsyncTaskSharedPreferencesEmulatorMaterial DesignLint WarningsServiceStoring Files in Internal & External StorageWebViewProject SDK versionsRecyclerViewGoogle Maps API v2 for AndroidPorterDuff Mode9-Patch ImagesAndroid NDKRecyclerView DecorationsCamera 2 APIViewPagerCardViewHttpURLConnectionSQLiteADB (Android Debug Bridge)ButterKnifeSupporting Screens With Different Resolutions, SizesGlideRetrofit2DialogACRAGreenDAOFormatting StringsNotificationsAlarmManagerFragmentsHandlerCreating Custom ViewsBroadcastReceiverActivitySnackbarRuntime Permissions in API-23 +Logging and using LogcatVectorDrawable and AnimatedVectorDrawableTools AttributesToastInterfacesAnimatorsLocationTheme, Style, AttributeThe Manifest FileParcelableMediaPlayerMultidex and the Dex Method LimitData Synchronization with Sync AdapterMenuInstant Run in Android StudioPicassoBluetooth and Bluetooth LE APIRoboGuiceMemory LeaksUniversal Image LoaderVolleyWidgetsDate and Time PickersIntegrate Google Sign InIn-app BillingFloatingActionButtonContentProviderDagger 2RealmUnit testing in Android with JUnitAndroid VersionsWi-Fi ConnectionsSensorManagerLocalization with resources in AndroidProgressBarCustom FontsVibrationGoogle Awareness APIsText to Speech(TTS)UI LifecycleSpinnerData Encryption/DecryptionTesting UI with EspressoWriting UI tests - AndroidGreenRobot EventBusOkHttpEnhancing Android Performance Using Icon FontsHandling Deep LinksCanvas drawing using SurfaceViewFirebaseCrash Reporting ToolsCheck Internet ConnectivityFacebook SDK for AndroidUnzip File in AndroidAndroid Places APICreating your own libraries for Android applicationsGsonDevice Display MetricsTextViewListViewBuilding Backwards Compatible AppsLoaderProGuard - Obfuscating and Shrinking your codeDetect Shake Event in AndroidTypedef Annotations: @IntDef, @StringDefCapturing ScreenshotsMVP ArchitectureOrientation ChangesXposedSecurityPackageManagerImageViewGesture DetectionDoze ModeAndroid Sound and MediaSearchViewCamera and GalleryCallback URLTwitter APIsDrawablesColorsConstraintLayoutRenderScriptFrescoSwipe to RefreshAutoCompleteTextViewInstalling apps with ADBIntentServiceAdMobImplicit IntentsPublish to Play StoreFirebase Realtime DataBaseImage CompressionEmail ValidationKeyboardButtonTextInputLayoutBottom SheetsCoordinatorLayout and BehaviorsEditTextAndroid Paypal Gateway IntegrationFirebase App IndexingFirebase Crash ReportingDisplaying Google AdsAndroid Vk SdkLocalized Date/Time in AndroidCount Down TimerBarcode and QR code readingOtto Event BusTransitionDrawablePort Mapping using Cling library in AndroidCreating Overlay (always-on-top) WindowsExoPlayerInter-app UI testing with UIAutomatorMediaSessionSpeech to Text ConversionFileProviderPublish .aar file to Apache Archiva with GradleXMPP register login and chat simple exampleAndroid AuthenticatorRecyclerView and LayoutManagersAudioManagerJob SchedulingAccounts and AccountManagerIntegrate OpenCV into Android StudioSplit Screen / Multi-Screen ActivitiesThreadMediaStoreTime UtilsTouch EventsFingerprint API in androidMVVM (Architecture)BottomNavigationViewORMLite in androidYoutube-APITabLayoutRetrofit2 with RxJavaDayNight Theme (AppCompat v23.2 / API 14+)ShortcutManagerLruCacheJenkins CI setup for Android ProjectsZip file in androidVector DrawablesfastlaneDefine step value (increment) for custom RangeSeekBarGetting started with OpenGL ES 2.0+Check Data ConnectionAndroid Java Native Interface (JNI)FileIO with AndroidPerformance OptimizationRobolectricMoshiStrict Mode Policy : A tool to catch the bug in the Compile Time.Internationalization and localization (I18N and L10N)Fast way to setup Retrolambda on an android project.How to use SparseArrayFirebase Cloud MessagingShared Element TransitionsAndroid ThingsVideoViewViewFlipperLibrary Dagger 2: Dependency Injection in ApplicationsFormatting phone numbers with pattern.How to store passwords securelyAndroid Kernel OptimizationPaintAudioTrackWhat is ProGuard? What is use in Android?Create Android Custom ROMsJava on AndroidPagination in RecyclerViewGenymotion for androidHandling touch and motion eventsCreating Splash screenConstraintSetCleverTapPublish a library to Maven Repositoriesadb shellPing ICMPAIDLAndroid programming with KotlinAutosizing TextViewsSign your Android App for ReleaseContextActivity RecognitionSecure SharedPreferencesSecure SharedPreferencesBitmap CacheAndroid-x86 in VirtualBoxJCodecDesign PatternsOkioGoogle signin integration on androidTensorFlowAndroid game developmentNotification Channel Android OBluetooth Low EnergyLeakcanaryAdding a FuseView to an Android ProjectAccessing SQLite databases using the ContentValues classEnhancing Alert DialogsHardware Button Events/Intents (PTT, LWP, etc.)SpannableStringLooperOptimized VideoViewGoogle Drive APIAnimated AlertDialog BoxAnnotation ProcessorSyncAdapter with periodically do sync of dataCreate Singleton Class for Toast MessageFastjsonAndroid Architecture ComponentsJacksonGoogle Play StoreLoading Bitmaps EffectivelyGetting system font names and using the fontsSmartcardConvert vietnamese string to english string Android

Orientation Changes

Other topics

Saving and Restoring Activity State

As your activity begins to stop, the system calls onSaveInstanceState() so your activity can save state information with a collection of key-value pairs. The default implementation of this method automatically saves information about the state of the activity's view hierarchy, such as the text in an EditText widget or the scroll position of a ListView.

To save additional state information for your activity, you must implement onSaveInstanceState() and add key-value pairs to the Bundle object. For example:

public class MainActivity extends Activity {
    static final String SOME_VALUE = "int_value";
    static final String SOME_OTHER_VALUE = "string_value";

    @Override
    protected void onSaveInstanceState(Bundle savedInstanceState) {
        // Save custom values into the bundle
        savedInstanceState.putInt(SOME_VALUE, someIntValue);
        savedInstanceState.putString(SOME_OTHER_VALUE, someStringValue);
        // Always call the superclass so it can save the view hierarchy state
        super.onSaveInstanceState(savedInstanceState);
    }
}

The system will call that method before an Activity is destroyed. Then later the system will call onRestoreInstanceState where we can restore state from the bundle:

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState);
    // Restore state members from saved instance
    someIntValue = savedInstanceState.getInt(SOME_VALUE);
    someStringValue = savedInstanceState.getString(SOME_OTHER_VALUE);
}

Instance state can also be restored in the standard Activity#onCreate method but it is convenient to do it in onRestoreInstanceState which ensures all of the initialization has been done and allows subclasses to decide whether to use the default implementation. Read this stackoverflow post for details.

Note that onSaveInstanceState and onRestoreInstanceState are not guaranteed to be called together. Android invokes onSaveInstanceState() when there's a chance the activity might be destroyed. However, there are cases where onSaveInstanceState is called but the activity is not destroyed and as a result onRestoreInstanceState is not invoked.

Saving and Restoring Fragment State

Fragments also have a onSaveInstanceState() method which is called when their state needs to be saved:

public class MySimpleFragment extends Fragment {
    private int someStateValue;
    private final String SOME_VALUE_KEY = "someValueToSave";
   
    // Fires when a configuration change occurs and fragment needs to save state
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        outState.putInt(SOME_VALUE_KEY, someStateValue);
        super.onSaveInstanceState(outState);
    }
}

Then we can pull data out of this saved state in onCreateView:

public class MySimpleFragment extends Fragment {
   // ...

   // Inflate the view for the fragment based on layout XML
   @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.my_simple_fragment, container, false);
        if (savedInstanceState != null) {
            someStateValue = savedInstanceState.getInt(SOME_VALUE_KEY);
            // Do something with value if needed
        }
        return view;
   }
}

For the fragment state to be saved properly, we need to be sure that we aren't unnecessarily recreating the fragment on configuration changes. This means being careful not to reinitialize existing fragments when they already exist. Any fragments being initialized in an Activity need to be looked up by tag after a configuration change:

public class ParentActivity extends AppCompatActivity {
    private MySimpleFragment fragmentSimple;
    private final String SIMPLE_FRAGMENT_TAG = "myfragmenttag";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        if (savedInstanceState != null) { // saved instance state, fragment may exist
           // look up the instance that already exists by tag
           fragmentSimple = (MySimpleFragment)  
              getSupportFragmentManager().findFragmentByTag(SIMPLE_FRAGMENT_TAG);
        } else if (fragmentSimple == null) { 
           // only create fragment if they haven't been instantiated already
           fragmentSimple = new MySimpleFragment();
        }
    }
}

This requires us to be careful to include a tag for lookup whenever putting a fragment into the activity within a transaction:

public class ParentActivity extends AppCompatActivity {
    private MySimpleFragment fragmentSimple;
    private final String SIMPLE_FRAGMENT_TAG = "myfragmenttag";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // ... fragment lookup or instantation from above...
        // Always add a tag to a fragment being inserted into container
        if (!fragmentSimple.isInLayout()) {
            getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.container, fragmentSimple, SIMPLE_FRAGMENT_TAG)
                .commit();
        }
    }
}

With this simple pattern, we can properly re-use fragments and restore their state across configuration changes.

Retaining Fragments

In many cases, we can avoid problems when an Activity is re-created by simply using fragments. If your views and state are within a fragment, we can easily have the fragment be retained when the activity is re-created:

public class RetainedFragment extends Fragment {
    // data object we want to retain
    private MyDataObject data;

    // this method is only called once for this fragment
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // retain this fragment when activity is re-initialized
        setRetainInstance(true);
    }

    public void setData(MyDataObject data) {
        this.data = data;
    }

    public MyDataObject getData() {
        return data;
    }
}

This approach keeps the fragment from being destroyed during the activity lifecycle. They are instead retained inside the Fragment Manager. See the Android official docs for more information.

Now you can check to see if the fragment already exists by tag before creating one and the fragment will retain it's state across configuration changes. See the Handling Runtime Changes guide for more details.

Locking Screen Orientation

If you want to lock the screen orientation change of any screen (activity) of your android application you just need to set the android:screenOrientation property of an <activity> within the AndroidManifest.xml:

<activity
    android:name="com.techblogon.screenorientationexample.MainActivity"
    android:screenOrientation="portrait"
    android:label="@string/app_name" >
    <!-- ... -->
</activity>

Now that activity is forced to always be displayed in "portrait" mode.

Manually Managing Configuration Changes

If your application doesn't need to update resources during a specific configuration change and you have a performance limitation that requires you to avoid the activity restart, then you can declare that your activity handles the configuration change itself, which prevents the system from restarting your activity.

However, this technique should be considered a last resort when you must avoid restarts due to a configuration change and is not recommended for most applications. To take this approach, we must add the android:configChanges node to the activity within the AndroidManifest.xml:

<activity android:name=".MyActivity"
          android:configChanges="orientation|screenSize|keyboardHidden"
          android:label="@string/app_name">

Now, when one of these configurations change, the activity does not restart but instead receives a call to onConfigurationChanged():

// Within the activity which receives these changes
// Checks the current device orientation, and toasts accordingly
@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    }
}

See the Handling the Change docs. For more about which configuration changes you can handle in your activity, see the android:configChanges documentation and the Configuration class.

Handling AsyncTask

Problem:

  • If after the AsyncTask starts there is a screen rotation the owning activity is destroyed and recreated.
  • When the AsyncTask finishes it wants to update the UI that may not valid anymore.

Solution:

Using Loaders, one can easily overcome the activity destruction/recreation.

Example:

MainActivity:

public class MainActivity extends AppCompatActivity 
        implements LoaderManager.LoaderCallbacks<Bitmap> {

    //Unique id for the loader
    private static final int MY_LOADER = 0; 

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        LoaderManager loaderManager = getSupportLoaderManager();

        if(loaderManager.getLoader(MY_LOADER) == null) {
            loaderManager.initLoader(MY_LOADER, null, this).forceLoad();
        }
    }

    @Override
    public Loader<Bitmap> onCreateLoader(int id, Bundle args) {
        //Create a new instance of your Loader<Bitmap>
        MyLoader loader = new MyLoader(MainActivity.this);
        return loader;
    }

    @Override
    public void onLoadFinished(Loader<Bitmap> loader, Bitmap data) {
        // do something in the parent activity/service
        // i.e. display the downloaded image
        Log.d("MyAsyncTask", "Received result: ");
    }

    @Override
    public void onLoaderReset(Loader<Bitmap> loader) {

    }
}

AsyncTaskLoader:

public class MyLoader extends AsyncTaskLoader<Bitmap> {
    private WeakReference<Activity> motherActivity;

    public MyLoader(Activity activity) {
        super(activity);
        //We don't use this, but if you want you can use it, but remember, WeakReference
        motherActivity = new WeakReference<>(activity);
    }

    @Override
    public Bitmap loadInBackground() {
        // Do work. I.e download an image from internet to be displayed in gui.
        // i.e. return the downloaded gui
        return result;
    }
}

Note:

It is important to use either the v4 compatibility library or not, but do not use part of one and part of the other, as it will lead to compilation errors. To check you can look at the imports for android.support.v4.content and android.content (you shouldn't have both).

Lock Screen's rotation programmatically

It is very common that during development, one may find very useful to lock/unlock the device screen during specific parts of the code.

For instance, while showing a Dialog with information, the developer might want to lock the screen's rotation to prevent the dialog from being dismissed and the current activity from being rebuilt to unlock it again when the dialog is dismissed.

Even though we can achieve rotation locking from the manifest by doing :

<activity
    android:name=".TheActivity"
    android:screenOrientation="portrait"
    android:label="@string/app_name" >
</activity>

One can do it programmatically as well by doing the following :

public void lockDeviceRotation(boolean value) {
    if (value) {
        int currentOrientation = getResources().getConfiguration().orientation;
        if (currentOrientation == Configuration.ORIENTATION_LANDSCAPE) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
        } else {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
        }
    } else {
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
        } else {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
        }
    }
}

And then calling the following, to respectively lock and unlock the device rotation

lockDeviceRotation(true)

and

lockDeviceRotation(false) 

Contributors

Topic Id: 4621

Example Ids: 16230,16231,16232,16233,16234,16611,21077

This site is not affiliated with any of the contributors.