summaryrefslogtreecommitdiffstats
path: root/src/net/hoopajoo/android/SoftKeys/Globals.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/hoopajoo/android/SoftKeys/Globals.java')
-rw-r--r--src/net/hoopajoo/android/SoftKeys/Globals.java193
1 files changed, 172 insertions, 21 deletions
diff --git a/src/net/hoopajoo/android/SoftKeys/Globals.java b/src/net/hoopajoo/android/SoftKeys/Globals.java
index 31d3f95..992805b 100644
--- a/src/net/hoopajoo/android/SoftKeys/Globals.java
+++ b/src/net/hoopajoo/android/SoftKeys/Globals.java
@@ -27,14 +27,21 @@ import java.util.Iterator;
import java.util.List;
import android.app.Application;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.AssetManager;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.util.Log;
+import android.widget.RemoteViews;
import android.widget.Toast;
public class Globals extends Application {
@@ -42,11 +49,42 @@ public class Globals extends Application {
private String android_id = null;
private String LOG = "SoftKeys.Global";
+ private boolean mBooted = false;
public boolean restartKeys = false;
public int homeCounter = 0;
public boolean didInitNotifications = false;
public boolean firstRun = true;
+ // simple typedef used to make the notifications a bit more generic
+ private class NotificationButton {
+ String mPrefKey;
+ RemoteViews mView;
+ int mIconId;
+ Drawable mIcon;
+ String mButtonText;
+ String mAction;
+ String mExtraString;
+
+ NotificationButton( String text, String pref, RemoteViews view, Drawable d, int icon, String act, String extra ) {
+ mButtonText = text;
+ mPrefKey = pref;
+ mView = view;
+ mIconId = icon;
+ mIcon = d;
+ mAction = act;
+ mExtraString = extra;
+ }
+
+ NotificationButton( String text, String pref, RemoteViews view, Drawable d, int icon, String act ) {
+ this( text, pref, view, d, icon, act, null );
+ }
+
+ NotificationButton( String text, String pref, int icon, String act ) {
+ this( text, pref, null, null, icon, act, null );
+ }
+
+ }
+
// interface to root context class
public RootContext getRootContext() throws Exception {
if( mRootContext == null ) {
@@ -185,31 +223,144 @@ public class Globals extends Application {
@Override
public void onCreate() {
- // warn if we don't notice some binaries we need
- for( String name : new String[] { "/system/bin/su" } ) {
- File check = new File( name );
- try {
- if( ! check.exists() ) {
- Toast.makeText( this, "Failed to find file: " + name + ", SoftKeys may not function", Toast.LENGTH_LONG ).show();
+ // init prefs defaults
+ PreferenceManager.setDefaultValues( this, R.xml.prefs, true );
+ }
+
+ // this used to be oncreate, but we can't have it there since we register for a boot receiver now
+ // since the only entry points are the receiver and keys, we'll run this from their oncreate or whatever
+ // and it will only run once then we'll flag it so we don't do it again
+ public void bootup() {
+ if( ! mBooted ) {
+ // warn if we don't notice some binaries we need
+ for( String name : new String[] { "/system/bin/su" } ) {
+ File check = new File( name );
+ try {
+ if( ! check.exists() ) {
+ Toast.makeText( this, "Failed to find file: " + name + ", SoftKeys may not function", Toast.LENGTH_LONG ).show();
+ }
+ }catch( Exception e ) {
+ Toast.makeText( this, "Unable to check for file: " + name, Toast.LENGTH_LONG ).show();
+ }
+
+ }
+
+ android_id = Settings.Secure.getString(this.getContentResolver(), Settings.Secure.ANDROID_ID);
+
+ // init the shell
+ try{
+ getRootContext();
+ }catch( Exception e ) {
+ Toast.makeText( this, "Failed to initialize root context", Toast.LENGTH_LONG );
+ }
+
+ restartService();
+ initNotifications();
+ mBooted = true;
+ }
+ }
+
+ public void initNotifications() {
+ // Add notification buttons
+ SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences( this );
+ if( ! didInitNotifications ) {
+ String ns = Context.NOTIFICATION_SERVICE;
+ NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
+ Context context = getApplicationContext();
+
+ // note: notification theming is kind of weird because of the way the notification manager
+ // handles icons, the icon in the bar itself when the status bar is closed HAS to come
+ // from the package creating the notification. We can however use any custom layouts
+ // for the actual notification when the bar is open. So if we are using custom notifications
+ // I just make the icon empty in the status bar which looks odd, but if we don't it would
+ // need to be an icon from this package and not from the theme which would mean the pull
+ // down notification would look different from the icon in the status bar itself which would
+ // be annoying.
+ //
+ // However is technically is possibly to theme these to an extent currently it's just
+ // not very ideal.
+ NotificationButton[] nb = new NotificationButton[ 5 ];
+ Theme theme = new Theme( this, settings.getString( "theme", null ) );
+ nb[ 0 ] = new NotificationButton( "SoftKeys", "nb_softkeys",
+ R.drawable.icon,
+ Intent.ACTION_MAIN );
+ nb[ 1 ] = new NotificationButton( "Menu", "nb_menu",
+ theme.getRemoteViews( new String[] { "notification_menu" } ),
+ theme.getDrawable( new String[] { "notification_menu" } ),
+ R.drawable.button_menu,
+ Keys.ACTION_MENU );
+ nb[ 2 ] = new NotificationButton( "Home", "nb_home",
+ theme.getRemoteViews( new String[] { "notification_home" } ),
+ theme.getDrawable( new String[] { "notification_home" } ),
+ R.drawable.button_home,
+ Keys.ACTION_HOME );
+ nb[ 3 ] = new NotificationButton( "Back", "nb_back",
+ theme.getRemoteViews( new String[] { "notification_back" } ),
+ theme.getDrawable( new String[] { "notification_back" } ),
+ R.drawable.button_back,
+ Keys.ACTION_BACK );
+ nb[ 4 ] = new NotificationButton( "Search", "nb_search",
+ theme.getRemoteViews( new String[] { "notification_search" } ),
+ theme.getDrawable( new String[] { "notification_search" } ),
+ R.drawable.button_search,
+ Keys.ACTION_SEARCH );
+
+ for( NotificationButton b : nb ) {
+ if( settings.getBoolean( b.mPrefKey, false ) ) {
+ Notification n = new Notification( b.mIconId, null, 0 );
+ Intent si = new Intent( b.mAction );
+ si.putExtra( "keyname", b.mExtraString );
+ if( b.mAction == Intent.ACTION_MAIN ) {
+ si.setPackage( getPackageName() );
+ }else{
+ //si.setPackage( getPackageName() );
+ si.setClass( this, Keys.class );
+ }
+ PendingIntent i = PendingIntent.getActivity( this, 0, si, 0 );
+
+ // if we got a drawable but no view then set up our own remote view
+ // and add in their drawable
+ if( b.mView == null && b.mIcon != null ) {
+ b.mView = new RemoteViews( getPackageName(), R.layout.notification_bar_shortcut );
+ // we run the drawable through resizeimage because that will rasterize it if it's
+ // not already a bitmapdrawable
+ b.mView.setImageViewBitmap( R.id.nb_image,
+ ((BitmapDrawable)Generator.resizeImage( b.mIcon, 48, 48 )).getBitmap()
+ );
+ b.mView.setTextViewText( R.id.nb_text, "Press SoftKeys " + b.mButtonText + " Button" );
+ }
+
+ if( b.mView != null ) {
+ // discard icon, use the remote view instead
+ n.icon = -1; // this will make it draw a blank, this kind of sucks
+ // but looking through notificationmanager and statusbarservice
+ // you have to post some kind of icon, that id is based on the calling
+ // package, and that icon is always added to the bar
+ n.contentView = b.mView;
+ n.contentIntent = i;
+ }else{
+ n.setLatestEventInfo( context, b.mButtonText,
+ b.mAction == Intent.ACTION_MAIN ? "Start SoftKeys" :
+ "Press SoftKeys " + b.mButtonText + " Button", i
+ );
+ }
+
+ //Notification n = new Notification();
+ n.flags |= Notification.FLAG_NO_CLEAR;
+
+ // we use the same icon id as the notification id since it should be unique,
+ // note the first parm here is a notification id we can use to reference/remove stuff
+ // we're not passing an icon here
+ mNotificationManager.notify( b.mIconId, n );
+ }else{
+ mNotificationManager.cancel( b.mIconId );
}
- }catch( Exception e ) {
- Toast.makeText( this, "Unable to check for file: " + name, Toast.LENGTH_LONG ).show();
}
-
+ // this way every time you click a notification soft key it doesn't readd them all making
+ // them jump around as they are re-inserted
+ didInitNotifications = true;
}
-
- android_id = Settings.Secure.getString(this.getContentResolver(), Settings.Secure.ANDROID_ID);
-
- // init the shell
- try{
- getRootContext();
- }catch( Exception e ) {
- Toast.makeText( this, "Failed to initialize root context", Toast.LENGTH_LONG );
- }
-
- restartService();
}
-
public void restartService() {
// start the service
this.stopService( new Intent( this, SoftKeysService.class ) );