How to get notified about Android system theme change? - java

Android introduced Dark Theme in API level 29 and higher (https://developer.android.com/guide/topics/ui/look-and-feel/darktheme). To support Dark Theme in your own app your app's theme needs to inherit from DayNight theme.
But what if you did your own theming, is there any intent from Android to get noticed about the system theme change?

If you add android:configChanges="uiMode" to your activities in the manifest, when the user changes the theme, the onConfigurationChanged method is called. If you override that you can do all the related work in there. In order to check what the current theme is you can do the following:
val currentNightMode = configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
when (currentNightMode) {
Configuration.UI_MODE_NIGHT_NO -> {} // Night mode is not active, we're using the light theme
Configuration.UI_MODE_NIGHT_YES -> {} // Night mode is active, we're using dark theme
}
EDIT: Since the original question isn't specific to Kotlin, here is the Java version of the above for reference:
int currentNightMode = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK;
switch (currentNightMode) {
case Configuration.UI_MODE_NIGHT_NO:
// Night mode is not active, we're using the light theme
break;
case Configuration.UI_MODE_NIGHT_YES:
// Night mode is active, we're using dark theme
break;
}
(source)

Related

Android 12 and material you detection

I'm trying to update my theme with the new Material You, it's working when I select a color in Android parameter (Screenshot red part) but when I disable it (blue part) I've got the default value color set in the SDK xml.
Example with: #android:color/system_accent1_0
I want to know how to check when user select it or not (red or blue part in screenshot), this way i will use another theme when disable. I guess I need to use the new method: applyToActivitiesIfAvailable :
#Override
public void onCreate() {
super.onCreate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
DynamicColors.applyToActivitiesIfAvailable(this, R.style.AppDynamicTheme, (activity, themeResId) -> {
// ...implement your own logic here. Return `true` if dynamic colors should be applied.
return true; // <- How to know if it's enable or disable in Android parameter ?
});}
My 2nd question is about the icon of the application, when i put blank color in background of ic_launcher.xml it works but not with another color, do you know why ?
Thanks

Disable landscape orientation for phones but allow for tablets

So the general consensus is this; most people use their phones in portrait and most people use their tablet in landscape. Depending on which activity it is my app's layout goes crazy when you rotate on the phone to landscape and it just wouldn't be worth the time to fix considering users are unlikely to rotate here and have no reason to do so. I'm aware of the ole orientation="portrait" trick in the Manifest in the activity element, however this locks tablet users into portrait which wouldn't be appropriate. I would like to disable portrait on all my activities for tablet users yet simultaneously disable landscape on most all my activites for phone users. I tried to pull a fast one by making a layout-large-land folder and no layout-large folder, but that doesn't prevent the orientation from changing on tablets.
If you just use setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) from code you will catch interesting effect on Android 26+. If the system autorotation option is enabled and you hold phone in landscape orientation and start new Activity it will appears in landscape orientation and then rotate to portrait in a few seconds. You doesn't catch such effect if set android:screenOrientation="portrait" option in the AndroidManifest. But there are not way to have different rotation option into AndroidManifest for phone and tablet.
There's way to solve that if you wish lock portrait orientation on phone and unlock autorotation on tablet.
Set option android:screenOrientation="locked" in the AndroidManifest for each Activity in you project.
<activity android:name=".SomeActivity"
android:screenOrientation="locked" />
where "locked" – Locks the orientation to its current rotation, whatever that is. Added in API level 18 from Android docs
Then set in parent BaseActivity such code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
int orientation = getResources().getConfiguration().orientation;
if (isTablet()) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
} else if(orientation != Configuration.ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
There are a few ways to detect that current device is Tablet. Choose implementation of isTablet() method yourself.
I guess you can use a code like this in onCreate() method:
int screenLayoutSize = getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
if (screenLayoutSize == Configuration.SCREENLAYOUT_SIZE_SMALL || screenLayoutSize == Configuration.SCREENLAYOUT_SIZE_NORMAL) {
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
And don't specify any orientation in xml, so by default it switches in both mode.
My suggestion would be to first find the way to know at run-time whether the activity is being executed in a Tablet by invoking a resource as explained in this answer. Then set the orientation as explained in this answer.
-Do One thing put this on the in the res/values file as bools.xml or whatever (file names don't matter here):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">true</bool>
</resources>
and Put this one in res/values-sw600dp and res/values-xlarge:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">false</bool>
</resources>
and then into java class file write this below code in onCreate method:
if(getResources().getBoolean(R.bool.portrait_only)){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
Devices that are more than 600 dp in the smallest width direction.
see the below link for the how to add directories and file into android studio project

How to permanently Disable actionbar/navigationbar/statusbar android 4.2.2

I have a rooted device that runs a custom launcher, I need to remove the actionbar/navigationbar/statusbar so that only the launcher can be used, and non of the native android stuff can be accessed.
I've tried almost all of the method's I could find on stackoverflow.
So I really help trying to figure out why this is not working.
I've also tried using immersive UI flags, but this still lets you access the navigation changes when you change focus.
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
hideSystemUI();
}
}
private void hideSystemUI() {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
You can't disable the statusbar or navigationbar from AndroidManifest.xml. The only thing you could do is start immersive mode, but that would only hide them. So they would be still accessible.
You can take a look at GravityBox' sources, they disable/enable the navigationbar with root.
You can use themes that have no action bar and use fullscreen.
eg android:Theme.Holo.NoActionBar.Fullscreen
In your styles.xml
<resources>
<style name="AppBaseTheme"
parent="android:Theme.Holo.NoActionBar.Fullscreen"/>
<style name="AppTheme"
parent="AppBaseTheme">
// to do...
Have a look here:
Using Platform Styles and Themes
You can also set you app to be the home launcher for the device.
In terms of preventing people access to the settings, 4.2.2 is not helpful, and this is difficult outside of lollipop, where user accounts can be created with restricted access. As the user can always pull down to get the settings.
There are apps you can use that prevent users from uninstalling apps and making changes to settings. These are password protected, and can work well with other restrictive measures.

ActionBar doesn't shows up when installed to Android Gingerbread

I've used a custom Dialog theme which i name poptheme and when i installed it to Gingerbread, the action bar doesn't shows up but when i installed it to Kitkat it works fine.
Since it's a dialog theme, a customized a new theme because i can't put an action bar using the theme theme.dialog. It worked fine on my phone which has Kitkat version, but when i try to run it on Gingerbread version, the layout is not what i wanted it to look like.
This is the code in my onCreate() for the customized dialog theme:
this.requestWindowFeature(Window.FEATURE_ACTION_BAR);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND,
WindowManager.LayoutParams.FLAG_DIM_BEHIND);
LayoutParams params = this.getWindow().getAttributes();
params.alpha = 1.0f;
params.dimAmount = 0.7f;
params.height=250;
params.width=420;
this.getWindow().setAttributes((android.view.WindowManager.LayoutParams) params);
// This sets the window size, while working around the IllegalStateException thrown by ActionBarView
// this.getWindow().setLayout(420,250);
// this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
setContentView(R.layout.activity_main);
//getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,R.drawable.ic_launcher);
Window.FEATURE_ACTION_BAR was added in API 11 (Android 3.0) so this approach won't work for Gingerbread (API 9/10).
You will need to use Android support library.
In below API 11 Action Bar Showed as a menu
click on Menu Button to see your Action Bar
Action Bar Features was Added in API 11 .
For Backward Compatibility Please use
ActionBarSherlock
Actionbar sherlock link

Remove Recent Apps Button From Navigation Bar

I am currently developing an app and I would like to have a little more control over it then usual without having to root the device.
I would like to remove the capability of the recent apps button in the navigation bar, or at least make it do something else from the default actions. Is there a way to do this? I'm sure there is since SureLock does the same thing.
Thanks
I have found a workaround for this on this website:http://www.juliencavandoli.com/how-to-disable-recent-apps-dialog-on-long-press-home-button/
you need to add this permission: android.permission.REORDER_TASKS
And add this code:
public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
if( !hasFocus)
{
ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
am.moveTaskToFront(getTaskId(), ActivityManager.MOVE_TASK_WITH_HOME );
sendBroadcast( new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS) );
}
}
It is not possible to override the recent apps button.
There is no KeyEvent like there is for the Back Button, and as such this feature is not available.
See documentation here: http://developer.android.com/reference/android/view/KeyEvent.html
You may not be able to disable a button, but you can disable the app that is associated with it. I don't know how it is done, but I have seen kiosk app (for non-rooted devices) that disallow other apps from loading.

Categories

Resources