JSON Schema To PoJo

http://www.jsonschema2pojo.org/

Handles Gson annotations too.

Advertisements

How To Have Multiple Launcher Icons In One Android APK Install For Different Activities

If you’ve ever installed Facebook from the Google Play store and noticed it adds 2 launcher icons (Facebook and Fb Chat) and wondered how they do this (have multiple launcher icons in one install bound to different activities) here is how to achieve this.

Step 1) For each activity you wish to expose an icon for in your Android app, add a corresponding “android:icon” attribute to your in AndroidManifest.xml:

android:icon="@drawable/power_saver_settings_app_icon"

Step 2) The key to getting this working is also adding an “android:taskAffinity” attribute with a unique value for each activity. Note that in the example below I just used the fully qualified package name + activity name. You can use any value you want here though:

android:taskAffinity="com.logicvoid.androidadvancedsettings.PowerSaverSettingsActivity"

Something to note is that the icon you define in the application section of AndroidManifest.xml (<application android:icon="@drawable/app_icon"..) will NOT be visible in the launcher, however it is still important to include as the Google Play store consumes this asset and will display it representing your application.

Complete AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.logicvoid.powersaversettings"
    android:versionCode="3"
    android:versionName="2.0" >

    <uses-sdk android:minSdkVersion="15" />
    

    <application
        android:icon="@drawable/app_icon"
        android:label="@string/app_name" >
        
        <activity            
            android:icon="@drawable/power_saver_settings_app_icon"
            android:name=".PowerSaverSettingsActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"
            android:label="@string/power_saver_settings_launcher_name" 
            android:taskAffinity="com.logicvoid.androidadvancedsettings.PowerSaverSettingsActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <activity            
            android:icon="@drawable/roaming_guard_settings_app_icon"
            android:name=".RoamingGuardsSettingsActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"
            android:label="@string/roaming_guards_settings_launcher_name"
            android:taskAffinity="com.logicvoid.androidadvancedsettings.RoamingGuardsSettingsActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Boiler Plate Android ListPreference Implementation Example

/values/arrays.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="pref_capacitive_backlight_entries">        
        <item>Off</item>
        <item>Dim</item>
        <item>Full On (Default)</item>
    </string-array>
    <string-array name="pref_capacitive_backlight_values">        
        <item>0</item>
        <item>2</item>
        <item>20</item>
    </string-array>
</resources>

/xml/misc_prefs.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen android:key="sense_pref_root"
  xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceCategory android:title="Misc Tweaks">
       	<ListPreference android:entries="@array/pref_capacitive_backlight_entries" android:title="Capacitive Backlight" android:key="pref_capacitive_backlight" android:entryValues="@array/pref_capacitive_backlight_values" android:summary="Brightness of backlight behind bottom capacitive buttons" android:defaultValue="20" />
    </PreferenceCategory>
</PreferenceScreen>

MiscActivity.java


package com.roman.tweaks.activities;

import com.roman.tweaks.R;
import com.roman.tweaks.ShellInterface;


import android.content.Context;

import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.provider.Settings;
import android.util.Log;

public class MiscActivity extends PreferenceActivity implements OnPreferenceChangeListener {
    String pref;

    Context mContext;

    
    private static final String PREF_CAPACITIVE_BACKLIGHT = "pref_capacitive_backlight";

    
    ListPreference mCapacitiveBacklight;
    
    /** Called when the activity is first created. */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mContext = this.getApplicationContext();
        addPreferencesFromResource(R.xml.misc_prefs);
        PreferenceScreen prefs = getPreferenceScreen();

   
        mCapacitiveBacklight = (ListPreference) prefs.findPreference(PREF_CAPACITIVE_BACKLIGHT);  
        mCapacitiveBacklight.setOnPreferenceChangeListener(this);          

    }    

    

    public boolean onPreferenceChange(Preference preference, Object newValue) {
        if (preference == mCapacitiveBacklight) {
            int valCapacitiveBacklight = Integer.valueOf((String) newValue);

            Settings.System.putInt(getContentResolver(), "tweaks_capacitive_backlight",
            		valCapacitiveBacklight);
            
            if (ShellInterface.isSuAvailable()) {
				ShellInterface.runCommand("echo '"+valCapacitiveBacklight+"' > /sys/devices/platform/leds-pm8058/leds/button-backlight/currents");
			}     
            
            
            return true;
        } 

        return false;
    }
}

AndroidManifest.xml Additions:

 <activity android:label="Tweaks - Misc Options" android:name=".activities.MiscActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
            </intent-filter>
        </activity>

Boiler Plate Android EditTextPreference Implementation Example

Create a new directory from root of project (xml) and add a new xml file (other_prefs):

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen android:title="Other Preferences"
	android:key="Other_prefscreen" xmlns:android="http://schemas.android.com/apk/res/android">
	<EditTextPreference android:title="Carrier Caption"
		android:key="pref_lockscreen_caption" android:summary="The text to display at top of the lockscreen"
		android:defaultValue="Warm TwoPointThree" android:dialogTitle="Lockscreen caption" />
</PreferenceScreen>

Create a new Activity under /src (OtherActivity.java)

package com.roman.tweaks.activities;

import com.roman.tweaks.R;
import com.roman.tweaks.ShellInterface;

import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.provider.Settings;

public class OtherActivity extends PreferenceActivity implements
		OnPreferenceChangeListener {

	public static final String TAG = "OtherActivity";

	// String keys for preference lookup
	private static final String PREF_CARRIER_CAPTION = "pref_lockscreen_caption";

	private EditTextPreference mLockscreenCaptionPref;

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

		addPreferencesFromResource(R.xml.other_prefs);

		// get UI object references
		PreferenceScreen prefSet = getPreferenceScreen();

		mLockscreenCaptionPref = (EditTextPreference) prefSet
				.findPreference(PREF_CARRIER_CAPTION);

		mLockscreenCaptionPref.setOnPreferenceChangeListener(this);
	}

	
	public boolean onPreferenceChange(Preference preference, Object newValue) {

		if (preference == mLockscreenCaptionPref) {

			String inputCarrierText = String.valueOf((String) newValue);
			Settings.System.putString(getContentResolver(),
					"tweaks_lockscreen_Caption", inputCarrierText);
			
			// Perform functions on preference change
			if (ShellInterface.isSuAvailable()) {
				ShellInterface.runCommand("echo '"+inputCarrierText+"' > /system/customize/lock_carrier.txt");
			}
			return true;

		}

		return false;
	}

}

Used in Warm Tweaks. See LockScreensActivity.java

How To Resolve Invalid Project Description Error in Eclipse Working on Android Project

Frequently when I import projects from GIT via EGIT in Eclipse I  get the error “Invalid Project Description”  This bugged the hell out of me.

There are two kinds of places where projects can be located:

1) In the “default” location. This means that the project directory is a direct child directory of the workspace directory (aka the platform instance location), and the project directory name matches the project name.

2) Outside the default location, in a directory that is neither a parent or child of the platform instance location. In this case the directory name does not need to match the project name.

To ensure a successful import you have to make sure the directory you are creating inside of your \workspace\ dir matches that of the name defined in the .project file.

In my example: \workspace3\warmupdater is the same name that is defined in the .project file.  This will yield a successful import without the error “Invalid Project Description”

<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>warmupdater</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
...
..

Source

Launch Activity/Service On Android Boot

OnBootReceiver.java

package com.logicvoid.voguetools;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

public  class OnBootReceiver extends  BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
         if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
              Log.d("VogueTools", "Got the Boot Event>>>");
              // do your stuff for example, start a background service directly
              // here
              Toast.makeText(context, "Testing From VogueTools", Toast.LENGTH_LONG).show();

         }
    }
}

manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.logicvoid.voguetools"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".MainActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

		<!--   Handling for On Boot Receiver -->
		 <receiver android:name=".OnBootReceiver"  android:enabled="true"  android:exported="false"  android:label="OnBootReceiver">
		    <intent-filter>
		        <action android:name="android.intent.action.BOOT_COMPLETED" />
		    </intent-filter>
		</receiver>
		 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
		<!-- End Handling for On Boot Receiver -->

    </application>
    <uses-sdk android:minSdkVersion="4" />

</manifest>

For reference. the Context passed in the onReceive is that of the Application, not a specific Activity.

If you’re doing anything that is context sensitive like dealing with preferences in your application, perhaps using appContext.getSharedPreferences. Use getApplicationContext() within your application to ensure the preferences will be read from both the BroadcastReceiver onReceive and the application itself. As the onReceive Context is that of the application, they will be equal.