2018年9月18日 星期二

Use reflection to get framework hide variable value or resource value

Code snippet:

1. Get hide constant value
public static int getHideIntConstants(String classAndPkgName, String fieldName, int defaultValue){
    int fieldValue = defaultValue;

    Class<?> c = null;
    try {
        c = Class.forName(classAndPkgName);
        Field field = c.getDeclaredField(fieldName);
        field.setAccessible(true);
        fieldValue = field.getInt(null);
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (Exception e){
        e.printStackTrace();
    }
    String hesString = Integer.toHexString(fieldValue);
    Log.d(TAG, "fieldValue " + fieldName + ": " + fieldValue + " ; hex: " + hesString);
    return fieldValue;
}

2. Get hide constant value declared in inner class
public static int getTypeDisplayOverlayInt(Window window) {
    int typeDisplayOverlay = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;

    Class<?> c = null;
    try {
        c = Class.forName("android.view.WindowManager");
        Class<?>[] classes = c.getDeclaredClasses();
        for(Class innerClass: classes){
            if(innerClass.getName().contains("LayoutParams")){
                Field field = innerClass.getDeclaredField("TYPE_DISPLAY_OVERLAY");
                field.setAccessible(true);
                typeDisplayOverlay = field.getInt(window.getAttributes());
                break;
            }
        }
    } catch (Exception e){
        e.printStackTrace();
    }
    return typeDisplayOverlay;
}

3. Get resource value
public static int getStatusHeight(Context context) {
    int statusBarHeight = -1;
    try {
        Class<?> clazz = Class.forName("com.android.internal.R$dimen");
        Object object = clazz.newInstance();
        int height = Integer.parseInt(clazz.getField("status_bar_height").get(object).toString());
        statusBarHeight = context.getResources().getDimensionPixelSize(height);
    } catch (Exception e) {
        e.printStackTrace();
    }

    return statusBarHeight;
}

4. Get SystemUI apk recource value
public static String getDateFormat(Context context) {
    PackageManager pm = context.getPackageManager();
    try {
        Resources resources = pm.getResourcesForApplication("com.android.systemui");
        int id = resources.getIdentifier("abbrev_wday_month_day_no_year", "string", "com.android.systemui");
        if (id > 0) {
            return resources.getString(id);
        } else {
            return null;
        }

    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }
    return null;
}

2018年5月17日 星期四

How to fix INSTALL_FAILED_TEST_ONLY error

Reference:

https://www.jianshu.com/p/8f5730cab8fc
http://www.cnblogs.com/yongfengnice/p/7814016.html
https://blog.csdn.net/chf1142152101/article/details/70738868

Solution:

1. Add the following line into gradle.properties

    ......
    android.injected.testOnly=false


2. Click Android Studio "Build -> BuildAPK(s)" to generate apk

3. Sign key
4. If gradle version is test version, revise it to release version

buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.4.0-alpha3' //版本为测试版 } }

2018年4月6日 星期五

Get height of status bar

Reference:

https://gist.github.com/hamakn/8939eb68a920a6d7a498

Code snippet:

public static int getStatusHeight(Context context) {
    int statusBarHeight = -1;
    try {
        Class<?> clazz = Class.forName("com.android.internal.R$dimen");
        Object object = clazz.newInstance();
        int height = Integer.parseInt(clazz.getField("status_bar_height").get(object).toString());
        statusBarHeight = context.getResources().getDimensionPixelSize(height);
    } catch (Exception e) {
        e.printStackTrace();
    }

    return statusBarHeight;
}

Detect device orientation by OrientationEventListener

Reference:
http://blog.csdn.net/zxccxzzxz/article/details/52282256

Code snippet:
private int mLastRotation = -1;
mOrientationEventListener = new OrientationEventListener(this,
        SensorManager.SENSOR_DELAY_NORMAL) {
    @Override    public void onOrientationChanged(int orientation) {
        if (orientation == ORIENTATION_UNKNOWN) {
            return;
        }
        Display display = windowManager.getDefaultDisplay();
        int rotation = display.getRotation();
        if (mLastRotation == DEFAULT_ROTATION){
            mLastRotation = rotation;
        } else if (rotation != mLastRotation) {
            mLastRotation = rotation;
            // notify orientation change
        }
    }
};

2018年4月5日 星期四

Change the menu style on ActionBar

Reference:

http://www.itstrike.cn/Question/c9ee24fa-9e1a-4154-a304-1fd41d418561.html

Code snippet:

1. Background

AndroidManifest.xml
<application    ......
    android:theme="@style/AppTheme">

style.xml
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">   
    <!-- Customize actionbar overflow menu-->    <item name="actionOverflowMenuStyle">@style/My.Widget.Material.Light.PopupMenu.Overflow</item>    
</style>

<style name="My.Widget.Material.Light.PopupMenu.Overflow" parent="android:Widget.Material.Light.PopupMenu.Overflow">
    <item name="android:popupBackground">@drawable/my_popup_background_material</item>
</style>


drawable/my_popup_background_material.xml
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"       android:shape="rectangle">
    <corners            android:radius="12dp" />
    <solid            android:color="@color/action_bar_color" />
</shape>

2. List choice background
activity_layout.xml
......
<android.support.v7.widget.Toolbar    android:id="@+id/tool_bar"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:background="@color/action_bar_color"    android:theme="@style/AppTheme.AppBarOverlay"    app:contentInsetStartWithNavigation="0dp"    app:popupTheme="@style/AppTheme.PopupOverlay" >

style.xml
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light">
    <item name="android:textColor">@color/list_item_title</item>
    <item name="android:textSize">18sp</item>
    <item name="android:textStyle">normal</item>
    <item name="android:listChoiceBackgroundIndicator">@drawable/my_list_choice_background_material</item>
</style>

drawable/my_list_choice_background_material.xml
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"        android:color="@color/list_highlight_material">
    <item>
        <shape android:shape="rectangle">
            <corners android:radius="12dp"/>
            <solid android:color="@color/action_bar_color" />
        </shape>
    </item>
</ripple>

How to import org.apache.http library to Android Studio

Reference:

https://dotblogs.com.tw/newmonkey48/2016/02/22/140802

Code snippet:

build.gradle

android {
    useLibrary 'org.apache.http.legacy'
}

Add a customized theme to AlertDialog

Reference:

http://blog.supenta.com/2014/07/02/how-to-style-alertdialogs-like-a-pro/

Code snippet:

Context mThemeContext = new ContextThemeWrapper(this, R.style.customized_theme);
View dialogView = View.inflate(mThemeContext, R.layout.my_dialog, null);
AlertDialog.Builder aBuilder = new AlertDialog.Builder(mThemeContext);
aBuilder.setView(dialogView);

// setup your AlertDialog
......

AlertDialog aDialog = aBuilder.create();
aDialog.show();

2018年3月28日 星期三

Disabling screen shot capture in Android application

Reference:





只要在呼叫setContentView()之前設定FLAG_SECUREwindows flag,這個頁面就無法被截圖或錄影
按  hardware key截圖時,會出現下列的log

01-01 21:11:50.538 10930-10930/? D/ScreenshotUtils: notifyScreenShotError, first screenshot

Code snippet:

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
            WindowManager.LayoutParams.FLAG_SECURE);

    setContentView(R.layout.activity_main);
    ...
}

2018年2月5日 星期一

Add/Remove Toolbar elevation

Reference:

http://blog.iamsuleiman.com/add-a-toolbar-elevation-on-pre-lollipop/
https://www.reddit.com/r/androiddev/comments/2k50fw/elevation_on_toolbar_not_working_on_prelollipop/
https://www.jianshu.com/p/802545cec682

Code snippet:

Add elevation
toolbar.setElevation(elevation);

Remove elevation
toolbar.setElevation(0);

Difference between removing an app from recent app list and click “Force Stop” button in Settings app info page

Reference:

https://android.stackexchange.com/questions/132929/difference-between-killing-an-app-by-clearing-it-from-recent-apps-menu-and-forc

Description:

從 Recent app list將app移除,並不會kill掉app process,只會將activity關閉,背景在執行service並不會停止運作。要將整個process kill掉,要從Settings app info頁面,將app force stop。



Change the color of toolbar overflow icon

Reference:

Method 1:
https://snow.dog/blog/how-to-dynamicaly-change-android-toolbar-icons-color/
https://stackoverflow.com/questions/43537958/change-toolbar-overflow-icon-color/43539097
https://futurestud.io/tutorials/android-quick-tips-8-how-to-dynamically-tint-actionbar-menu-icons

Method 2:
https://www.murrayc.com/permalink/2014/10/28/android-changing-the-toolbars-text-color-and-overflow-icon-color/
https://stackoverflow.com/questions/27995461/appcompat-toolbar-change-overflow-icon-color-in-actionmode


Code snippet:

Method 1:
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
    <item name="android:textColorPrimary">@color/action_bar_text_color</item>
    <!-- change the overflow icon color (three vertical dots) -->    <item name="android:tint">@color/action_bar_overflow_icon_color</item>
    <item name="android:textSize">20sp</item>
    <item name="android:textStyle">bold</item>
    <item name="android:fontFamily">Roboto Medium</item>
</style>

2018年2月4日 星期日

Change the color of status bar and icon/text

Reference:

https://developer.android.com/training/material/theme.html
https://solinariwu.blogspot.tw/2017/05/android-status-bar.html

Code snippet:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize the status bar color -->    <item name="android:statusBarColor">@color/status_bar_color</item>
    <!-- If set, the status bar will be drawn such that it is compatible with a light status bar background -->    <item name="android:windowLightStatusBar">true</item>
</style>

2018年2月1日 星期四

Change navigation bar color

Reference:

https://stackoverflow.com/questions/27839105/android-lollipop-change-navigation-bar-color

Code snippet:

styles.xml
<item name="android:navigationBarColor">@color/theme_color</item>

XXX.java
window.setNavigationBarColor(@ColorInt int color)

Check if device is locked

Reference:

https://stackoverflow.com/questions/8317331/detecting-when-screen-is-locked

Code snippet:

KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
boolean isPhoneLocked = keyguardManager.inKeyguardRestrictedInputMode();

Completely transparent status bar and navigation bar

Reference:

https://stackoverflow.com/questions/29069070/completely-transparent-status-bar-and-navigation-bar-on-lollipop


Code snippet:


getWindow().setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
        WindowManager.LayoutParams.
FLAG_LAYOUT_NO_LIMITS);



<style name="FullScreenTheme" parent="@android:style/Theme.Translucent.NoTitleBar.Fullscreen">
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
</style>