diff --git a/app/build.gradle b/app/build.gradle
index 76d627b1a1889e0ef5719eee5715c13359aa0af6..adad8ee586ff288ba09fdb7b775e5670d5b3f0c0 100755
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -8,7 +8,7 @@ android {
         minSdkVersion 8
         targetSdkVersion 25
         versionCode 81
-        versionName "4.10"
+        versionName "4.11"
     }
 
     buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1a00f156062bda1000300347526a59cbc32f16b9..1ef09a116693cb05927274faae3c023898abdfd3 100755
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -10,6 +10,8 @@
         android:smallScreens="true" />
 
     <!-- permissions -->
+    <uses-permission android:name="android.permission.BLUETOOTH" />
+    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
diff --git a/app/src/main/java/ohi/andre/consolelauncher/LauncherActivity.java b/app/src/main/java/ohi/andre/consolelauncher/LauncherActivity.java
index a65f3ff822598ee2b8edd4e02f951836d2c25ac0..64cdc52da9febd51b7c93418bda8a120318e1c45 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/LauncherActivity.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/LauncherActivity.java
@@ -55,9 +55,9 @@ public class LauncherActivity extends Activity implements Reloadable {
     private CommandExecuter ex = new CommandExecuter() {
 
         @Override
-        public String exec(String input, int id) {
+        public String exec(String input) {
             try {
-                main.onCommand(input, id);
+                main.onCommand(input);
             } catch (NullPointerException e) {
                 e.printStackTrace();
             }
@@ -80,9 +80,9 @@ public class LauncherActivity extends Activity implements Reloadable {
     private Outputable out = new Outputable() {
 
         @Override
-        public void onOutput(String output, int id) {
+        public void onOutput(String output) {
             try {
-                ui.setOutput(output, id);
+                ui.setOutput(output);
             } catch (NullPointerException e) {
                 e.printStackTrace();
             }
@@ -266,39 +266,39 @@ public class LauncherActivity extends Activity implements Reloadable {
     public void onWindowFocusChanged(boolean hasFocus) {
         super.onWindowFocusChanged(hasFocus);
 
-        if (hasFocus) {
-            hideStatusBar();
-            if (ui != null) {
-                ui.focusTerminal();
-            }
+        if (ui != null) {
+            ui.focusTerminal();
         }
+        hideStatusBar();
     }
 
     @Override
     public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
-        switch (requestCode) {
-            case COMMAND_REQUEST_PERMISSION:
-                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
-                    ExecInfo info = main.getInfo();
-                    main.onCommand(info.calledCommand, info.calledCommandOutputId);
-                } else {
-                    ui.setOutput(getString(R.string.output_nopermissions), main.getInfo().calledCommandOutputId);
-                }
-                break;
-            case STORAGE_PERMISSION:
-                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
-                    finishOnCreate();
-                } else {
-                    Toast.makeText(this, R.string.permissions_toast, Toast.LENGTH_LONG).show();
-                    finish();
-                }
-                break;
-            case COMMAND_SUGGESTION_REQUEST_PERMISSION:
-                if (grantResults.length == 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
-                    ui.setOutput(getString(R.string.output_nopermissions), main.getInfo().calledCommandOutputId);
-                }
-                break;
-        }
+        try {
+            switch (requestCode) {
+                case COMMAND_REQUEST_PERMISSION:
+                    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+                        ExecInfo info = main.getInfo();
+                        main.onCommand(info.calledCommand);
+                    } else {
+                        ui.setOutput(getString(R.string.output_nopermissions));
+                    }
+                    break;
+                case STORAGE_PERMISSION:
+                    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+                        finishOnCreate();
+                    } else {
+                        Toast.makeText(this, R.string.permissions_toast, Toast.LENGTH_LONG).show();
+                        finish();
+                    }
+                    break;
+                case COMMAND_SUGGESTION_REQUEST_PERMISSION:
+                    if (grantResults.length == 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
+                        ui.setOutput(getString(R.string.output_nopermissions));
+                    }
+                    break;
+            }
+        } catch (Exception e) {}
     }
 
 }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/MainManager.java b/app/src/main/java/ohi/andre/consolelauncher/MainManager.java
index 8bc0c6c04e415d5988aea38f49901a0a29c6cf66..b74c2691898c18485c3c5b3792c4aa2eedbef54b 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/MainManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/MainManager.java
@@ -78,23 +78,23 @@ public class MainManager {
 
         CommandExecuter executer = new CommandExecuter() {
             @Override
-            public String exec(String input, int id) {
-                onCommand(input, id);
+            public String exec(String input) {
+                onCommand(input);
                 return null;
             }
         };
 
-        MusicManager music = new MusicManager(mContext, prefsMgr);
+        MusicManager music = new MusicManager(mContext, prefsMgr, out);
 
-        AppsManager appsMgr = new AppsManager(c, Boolean.parseBoolean(prefsMgr.getValue(PreferencesManager.COMPARESTRING_APPS)));
+        AppsManager appsMgr = new AppsManager(c, Boolean.parseBoolean(prefsMgr.getValue(PreferencesManager.COMPARESTRING_APPS)), out);
         AliasManager aliasManager = new AliasManager(prefsMgr);
 
         info = new ExecInfo(mContext, prefsMgr, group, aliasManager, appsMgr, music, cont, devicePolicyManager, componentName,
-                c, clearer, executer);
+                c, executer);
     }
 
     //    command manager
-    public void onCommand(String input, int id) {
+    public void onCommand(String input) {
         if (lastCommands.size() == LAST_COMMANDS_SIZE)
             lastCommands.remove(0);
 
@@ -107,9 +107,9 @@ public class MainManager {
         for (CmdTrigger trigger : triggers) {
             boolean r;
             try {
-                r = trigger.trigger(info, out, input, id);
+                r = trigger.trigger(info, out, input);
             } catch (Exception e) {
-                out.onOutput(Tuils.getStackTrace(e), id);
+                out.onOutput(Tuils.getStackTrace(e));
                 return;
             }
             if (r) {
@@ -147,17 +147,17 @@ public class MainManager {
     }
 
     interface CmdTrigger {
-        boolean trigger(ExecInfo info, Outputable out, String input, int id) throws Exception;
+        boolean trigger(ExecInfo info, Outputable out, String input) throws Exception;
     }
 
     class AliasTrigger implements CmdTrigger {
         @Override
-        public boolean trigger(ExecInfo info, Outputable out, String input, int id) {
+        public boolean trigger(ExecInfo info, Outputable out, String input) {
             String alias = info.aliasManager.getAlias(input);
             if (alias == null)
                 return false;
 
-            info.executer.exec(alias, id);
+            info.executer.exec(alias);
 
             return true;
         }
@@ -169,11 +169,11 @@ public class MainManager {
         final int COMMAND_NOTFOUND = 127;
 
         @Override
-        public boolean trigger(final ExecInfo info, final Outputable out, String input, final int id) throws Exception {
+        public boolean trigger(final ExecInfo info, final Outputable out, String input) throws Exception {
 
             if (CommandTuils.isSuRequest(input)) {
                 boolean su = Tuils.verifyRoot();
-                out.onOutput(info.res.getString(su ? R.string.su : R.string.nosu), id);
+                out.onOutput(info.res.getString(su ? R.string.su : R.string.nosu));
             } else {
                 boolean su = false;
                 if (CommandTuils.isSuCommand(input)) {
@@ -193,9 +193,9 @@ public class MainManager {
 
                         ShellUtils.CommandResult result = ShellUtils.execCommand(cmd, useSU, info.currentDirectory.getAbsolutePath());
                         if (result.result == COMMAND_NOTFOUND) {
-                            out.onOutput(mContext.getString(R.string.output_commandnotfound), id);
+                            out.onOutput(mContext.getString(R.string.output_commandnotfound));
                         } else {
-                            out.onOutput(result.toString(), id);
+                            out.onOutput(result.toString());
                         }
                     }
                 }.start();
@@ -208,7 +208,7 @@ public class MainManager {
     class AppTrigger implements CmdTrigger {
 
         @Override
-        public boolean trigger(ExecInfo info, Outputable out, String input, int id) {
+        public boolean trigger(ExecInfo info, Outputable out, String input) {
             String packageName = info.appsManager.findPackage(input, AppsManager.SHOWN_APPS);
             if (packageName == null) {
                 return false;
@@ -219,7 +219,7 @@ public class MainManager {
                 return false;
             }
 
-            out.onOutput(info.res.getString(R.string.starting_app) + Tuils.SPACE + intent.getComponent().getClassName(), id);
+            out.onOutput(info.res.getString(R.string.starting_app) + Tuils.SPACE + intent.getComponent().getClassName());
 
             mContext.startActivity(intent);
 
@@ -230,7 +230,7 @@ public class MainManager {
     class TuiCommandTrigger implements CmdTrigger {
 
         @Override
-        public boolean trigger(final ExecInfo info, final Outputable out, final String input, final int id) throws Exception {
+        public boolean trigger(final ExecInfo info, final Outputable out, final String input) throws Exception {
 
             final boolean[] returnValue = new boolean[1];
             Thread t = new Thread() {
@@ -239,7 +239,6 @@ public class MainManager {
                     super.run();
 
                     info.calledCommand = input;
-                    info.calledCommandOutputId = id;
 
                     try {
                         Command command = CommandTuils.parse(input, info, false);
@@ -252,11 +251,11 @@ public class MainManager {
                         if (returnValue[0]) {
                             String output = command.exec(info);
                             if(output != null) {
-                                out.onOutput(output, id);
+                                out.onOutput(output);
                             }
                         }
                     } catch (Exception e) {
-                        out.onOutput(e.toString(), id);
+                        out.onOutput(e.toString());
                     }
                 }
             };
diff --git a/app/src/main/java/ohi/andre/consolelauncher/UIManager.java b/app/src/main/java/ohi/andre/consolelauncher/UIManager.java
index d030c2d7850be6f9cc93641fb7d5eb3a4508a380..220df25ff591d050b80e60d32b77b156f6819f22 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/UIManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/UIManager.java
@@ -432,12 +432,12 @@ public class UIManager implements OnTouchListener {
                 if(suggestionsView != null) {
                     suggestionsView.removeAllViews();
                 }
-                trigger.exec(input, mTerminalAdapter.getCurrentOutputId());
+                trigger.exec(input);
             }
         });
-//        if(Boolean.parseBoolean(prefsMgr.getValue(PreferencesManager.SHOW_DONATE_MESSAGE))) {
-//            mTerminalAdapter.addMessager(new TerminalManager.Messager(65, context.getString(R.string.rate_donate_text)));
-//        }
+        if(Boolean.parseBoolean(prefsMgr.getValue(PreferencesManager.SHOW_DONATE_MESSAGE))) {
+            mTerminalAdapter.addMessager(new TerminalManager.Messager(20, context.getString(R.string.rate_donate_text)));
+        }
 
         ViewTreeObserver observer = rootView.getViewTreeObserver();
         final TextView device = deviceInfo;
@@ -473,7 +473,6 @@ public class UIManager implements OnTouchListener {
     }
 
     public void onStart() {
-        mTerminalAdapter.requestInputFocus();
         openKeyboard();
         mTerminalAdapter.scrollToEnd();
     }
@@ -486,8 +485,8 @@ public class UIManager implements OnTouchListener {
         mTerminalAdapter.focusInputEnd();
     }
 
-    public void setOutput(String string, int id) {
-        mTerminalAdapter.setOutput(string, id);
+    public void setOutput(String string) {
+        mTerminalAdapter.setOutput(string);
     }
 
     //    get device name
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/ExecInfo.java b/app/src/main/java/ohi/andre/consolelauncher/commands/ExecInfo.java
index c79c90fadf8869946a70795109ca9cb6c4c412c7..a8bb78398f805339bfb8da4bae37f21b607f5755 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/ExecInfo.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/ExecInfo.java
@@ -16,6 +16,7 @@ import android.os.Parcel;
 import java.io.File;
 import java.lang.reflect.Method;
 
+import ohi.andre.consolelauncher.commands.raw.flash;
 import ohi.andre.consolelauncher.managers.AliasManager;
 import ohi.andre.consolelauncher.managers.AppsManager;
 import ohi.andre.consolelauncher.managers.ContactManager;
@@ -75,8 +76,6 @@ public class ExecInfo {
 
     //	execute a command
     public CommandExecuter executer;
-    //  clear
-    public Runnable clearer;
     //	current set of args
     private Object[] args;
     //	uses su
@@ -84,11 +83,10 @@ public class ExecInfo {
 
 //    output when permission is needed
     public String calledCommand;
-    public int calledCommandOutputId;
 
     public ExecInfo(Context context, PreferencesManager prefsMgr, CommandGroup commandGroup, AliasManager alMgr, AppsManager appmgr, MusicManager p,
                     ContactManager c, DevicePolicyManager devicePolicyManager, ComponentName componentName,
-                    Reloadable r, Runnable cl, CommandExecuter executeCommand) {
+                    Reloadable r, CommandExecuter executeCommand) {
         this.res = context.getResources();
         this.commandGroup = commandGroup;
 
@@ -112,8 +110,6 @@ public class ExecInfo {
         this.component = componentName;
 
         this.reloadable = r;
-
-        this.clearer = cl;
     }
 
     public ExecInfo(Parcel parcel) {
@@ -148,6 +144,10 @@ public class ExecInfo {
         if (this.camera == null || this.isFlashOn)
             return;
 
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            flash.detachSurfaceTexture(null);
+        }
+
         this.camera.stopPreview();
         this.camera.release();
         this.camera = null;
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/raw/bluetooth.java b/app/src/main/java/ohi/andre/consolelauncher/commands/raw/bluetooth.java
new file mode 100644
index 0000000000000000000000000000000000000000..0d133ab770c3a9612991b81d04b7c9a6dab9337e
--- /dev/null
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/raw/bluetooth.java
@@ -0,0 +1,66 @@
+package ohi.andre.consolelauncher.commands.raw;
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.Context;
+import android.net.wifi.WifiManager;
+
+import ohi.andre.consolelauncher.R;
+import ohi.andre.consolelauncher.commands.CommandAbstraction;
+import ohi.andre.consolelauncher.commands.ExecInfo;
+import ohi.andre.consolelauncher.tuils.Tuils;
+
+public class bluetooth implements CommandAbstraction {
+
+    @Override
+    public String exec(ExecInfo info) {
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        if(adapter.getState() == BluetoothAdapter.STATE_ON) {
+            adapter.disable();
+            return info.context.getString(R.string.output_bluetooth) + Tuils.SPACE + "false";
+        } else {
+            adapter.enable();
+            return info.context.getString(R.string.output_bluetooth) + Tuils.SPACE + "true";
+        }
+    }
+
+    @Override
+    public int helpRes() {
+        return R.string.help_bluetooth;
+    }
+
+    @Override
+    public int minArgs() {
+        return 0;
+    }
+
+    @Override
+    public int maxArgs() {
+        return 0;
+    }
+
+    @Override
+    public int[] argType() {
+        return null;
+    }
+
+    @Override
+    public int priority() {
+        return 2;
+    }
+
+    @Override
+    public String[] parameters() {
+        return null;
+    }
+
+    @Override
+    public String onNotArgEnough(ExecInfo info, int nArgs) {
+        return null;
+    }
+
+    @Override
+    public int notFoundRes() {
+        return 0;
+    }
+
+}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/raw/clear.java b/app/src/main/java/ohi/andre/consolelauncher/commands/raw/clear.java
index 58793bd06178afd234900193e488470b3b782fed..ab4b5f58048427c3893a7ba7076cfdcc5bae5cfc 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/raw/clear.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/raw/clear.java
@@ -3,16 +3,18 @@ package ohi.andre.consolelauncher.commands.raw;
 import ohi.andre.consolelauncher.R;
 import ohi.andre.consolelauncher.commands.CommandAbstraction;
 import ohi.andre.consolelauncher.commands.ExecInfo;
+import ohi.andre.consolelauncher.tuils.Tuils;
 
 /**
  * Created by andre on 07/11/15.
  */
 public class clear implements CommandAbstraction {
 
+    public static final String CLEAR = "#clear#";
+
     @Override
     public String exec(ExecInfo info) throws Exception {
-        info.clearer.run();
-        return "";
+        return CLEAR;
     }
 
     @Override
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/raw/flash.java b/app/src/main/java/ohi/andre/consolelauncher/commands/raw/flash.java
index 14372a3c83954bb22d7ae643ef03ec85e7919539..f78e195733d192f2c489a7ef2292b48d8fe9c22b 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/raw/flash.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/raw/flash.java
@@ -1,58 +1,111 @@
 package ohi.andre.consolelauncher.commands.raw;
 
-import android.Manifest;
-import android.app.Activity;
-import android.content.pm.PackageManager;
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.hardware.Camera;
+import android.graphics.SurfaceTexture;
 import android.hardware.Camera.Parameters;
-import android.support.v4.app.ActivityCompat;
-import android.support.v4.content.ContextCompat;
+import android.hardware.camera2.CameraManager;
+import android.os.Build;
+
+import java.io.IOException;
 
-import ohi.andre.consolelauncher.LauncherActivity;
 import ohi.andre.consolelauncher.R;
 import ohi.andre.consolelauncher.commands.CommandAbstraction;
 import ohi.andre.consolelauncher.commands.ExecInfo;
-import ohi.andre.consolelauncher.tuils.Tuils;
 
 @SuppressWarnings("deprecation")
 public class flash implements CommandAbstraction {
 
     @Override
-    public String exec(ExecInfo info) {
-        if (!info.canUseFlash)
+    public String exec(final ExecInfo info) {
+        if (!info.canUseFlash) {
             return info.res.getString(R.string.output_flashlightnotavailable);
-
-        if (ContextCompat.checkSelfPermission(info.context, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
-            ActivityCompat.requestPermissions((Activity) info.context, new String[]{Manifest.permission.CAMERA}, LauncherActivity.COMMAND_REQUEST_PERMISSION);
-            return info.context.getString(R.string.output_waitingpermission);
         }
 
         final ExecInfo execInfo = info;
-        new Thread() {
-            @Override
-            public void run() {
-                super.run();
-
-                if (execInfo.camera == null)
-                    execInfo.initCamera();
-
-                if (!execInfo.isFlashOn) {
-                    execInfo.parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
-                    execInfo.camera.setParameters(execInfo.parameters);
-                    execInfo.camera.startPreview();
-                    execInfo.isFlashOn = true;
-                } else {
-                    execInfo.parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
-                    execInfo.camera.setParameters(execInfo.parameters);
-                    execInfo.camera.stopPreview();
-                    execInfo.isFlashOn = false;
+        final boolean flashOn = info.isFlashOn;
+
+        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+            new Thread() {
+                @Override
+                public void run() {
+                    super.run();
+
+                    if (execInfo.camera == null)
+                        execInfo.initCamera();
+
+                    if (!flashOn) {
+                        execInfo.parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
+                        execInfo.camera.setParameters(execInfo.parameters);
+
+                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+                            setSurfaceTexture(info.camera);
+                        }
+
+                        execInfo.camera.startPreview();
+                    } else {
+                        execInfo.parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
+                        execInfo.camera.setParameters(execInfo.parameters);
+
+                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+                            detachSurfaceTexture(info.camera);
+                        }
+
+                        execInfo.camera.stopPreview();
+                    }
                 }
+            }.start();
+        } else {
+            if(!flashOn) {
+                flashOnMarshy(info.context);
+            } else {
+                flashOffMarshy(info.context);
             }
-        }.start();
+        }
 
-        if (!execInfo.isFlashOn)
+        execInfo.isFlashOn = !flashOn;
+        if (execInfo.isFlashOn) {
             return info.res.getString(R.string.output_flashon);
-        else
+        } else {
             return info.res.getString(R.string.output_flashoff);
+        }
+    }
+
+    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+    public static void setSurfaceTexture(Camera camera) {
+        try {
+            camera.setPreviewTexture(new SurfaceTexture(0));
+        } catch (IOException e) {}
+    }
+
+    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+    public static void detachSurfaceTexture(Camera camera) {
+        try {
+            camera.setPreviewTexture(null);
+        } catch (IOException e) {}
+    }
+
+    @TargetApi(Build.VERSION_CODES.M)
+    private boolean flashOnMarshy(Context context) {
+        try {
+            CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
+            manager.setTorchMode(manager.getCameraIdList()[0], true);
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    @TargetApi(Build.VERSION_CODES.M)
+    private boolean flashOffMarshy(Context context) {
+        try {
+            CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
+            manager.setTorchMode(manager.getCameraIdList()[0], false);
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
     }
 
     @Override
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/AppsManager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/AppsManager.java
index d9a789138c10f53ae8c9a42295d1587f2f0b7dbd..a88cdf2312b5316a06e526d33b8030acfa4d7268 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/AppsManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/AppsManager.java
@@ -21,7 +21,9 @@ import java.util.List;
 import java.util.Map;
 
 import ohi.andre.comparestring.Compare;
+import ohi.andre.consolelauncher.R;
 import ohi.andre.consolelauncher.tuils.Tuils;
+import ohi.andre.consolelauncher.tuils.interfaces.Outputable;
 
 public class AppsManager {
 
@@ -42,6 +44,8 @@ public class AppsManager {
     private AppsHolder appsHolder;
     private List<AppInfo> hiddenApps;
 
+    private Outputable outputable;
+
     private boolean useCompareString;
 
     private BroadcastReceiver appsBroadcast = new BroadcastReceiver() {
@@ -56,11 +60,13 @@ public class AppsManager {
         }
     };
 
-    public AppsManager(Context context, boolean useCompareString) {
+    public AppsManager(Context context, boolean useCompareString, Outputable outputable) {
         this.context = context;
         this.mgr = context.getPackageManager();
         this.useCompareString = useCompareString;
 
+        this.outputable = outputable;
+
         SharedPreferences preferences = context.getSharedPreferences(APPS_PREFERENCES, Context.MODE_PRIVATE);
         prefsEditor = preferences.edit();
         fill(preferences);
@@ -139,6 +145,7 @@ public class AppsManager {
             ApplicationInfo info = mgr.getApplicationInfo(packageName, 0);
             AppInfo app = new AppInfo(packageName, info.loadLabel(mgr).toString(), 0);
             appsHolder.add(app);
+            outputable.onOutput(context.getString(R.string.app_installed) + Tuils.SPACE + packageName);
         } catch (NameNotFoundException e) {}
     }
 
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/MusicManager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/MusicManager.java
index e721e556809d9889db2af60f35b1ec8572a7465f..df211de26929d536182885fbd2686528e48352a7 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/MusicManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/MusicManager.java
@@ -16,6 +16,7 @@ import java.util.Random;
 import ohi.andre.comparestring.Compare;
 import ohi.andre.consolelauncher.tuils.Tuils;
 import ohi.andre.consolelauncher.tuils.broadcast.HeadsetBroadcast;
+import ohi.andre.consolelauncher.tuils.interfaces.Outputable;
 
 public class MusicManager implements OnCompletionListener {
 
@@ -29,6 +30,8 @@ public class MusicManager implements OnCompletionListener {
     private int currentSongIndex = 0;
     private File currentSong = null;
 
+    private Outputable outputable;
+
     //	headset broadcast
     private BroadcastReceiver headsetReceiver = new HeadsetBroadcast(new Runnable() {
         @Override
@@ -38,10 +41,12 @@ public class MusicManager implements OnCompletionListener {
     });
 
     //	constructor
-    public MusicManager(Context c, PreferencesManager preferencesManager) {
+    public MusicManager(Context c, PreferencesManager preferencesManager, Outputable outputable) {
         this.mp = new MediaPlayer();
         this.mp.setOnCompletionListener(this);
 
+        this.outputable = outputable;
+
         c.registerReceiver(headsetReceiver, new IntentFilter(Intent.ACTION_HEADSET_PLUG));
 
         boolean randomActive = Boolean.parseBoolean(preferencesManager.getValue(PreferencesManager.PLAY_RANDOM));
@@ -185,7 +190,7 @@ public class MusicManager implements OnCompletionListener {
 
     @Override
     public void onCompletion(MediaPlayer mp) {
-        next();
+        outputable.onOutput(next());
     }
 
     public void onHeadsetUnplugged() {
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/TerminalMAnager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/TerminalMAnager.java
index 30b8caac86c9429e8f59684b1e1dabd1cd86856c..a75197150f5265ffda7d00b1189b5f5c38339e88 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/TerminalMAnager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/TerminalMAnager.java
@@ -22,6 +22,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
+import ohi.andre.consolelauncher.commands.raw.clear;
 import ohi.andre.consolelauncher.tuils.SimpleMutableEntry;
 import ohi.andre.consolelauncher.tuils.Tuils;
 import ohi.andre.consolelauncher.tuils.interfaces.OnNewInputListener;
@@ -49,8 +50,11 @@ public class TerminalManager {
     public static final int INPUT = 10;
     public static final int OUTPUT = 11;
 
-    private int mCurrentOutputId = 0;
-    private int globalId = 0;
+//    private int globalId = 0;
+//    private int mCurrentOutputId = 0;
+
+    private boolean inputUp;
+    private int cmds = 0;
 
     private ScrollView mScrollView;
     private TextView mTerminalView;
@@ -58,22 +62,18 @@ public class TerminalManager {
     private Runnable mScrollRunnable = new Runnable() {
         @Override
         public void run() {
-            boolean inputHadFocus = mInputView.hasFocus();
             mScrollView.fullScroll(ScrollView.FOCUS_DOWN);
-            if (inputHadFocus)
-                requestInputFocus();
+            mInputView.requestFocus();
         }
     };
+
     private SkinManager mSkinManager;
 
     private OnNewInputListener mInputListener;
 
-    private boolean inputUp;
-
     private List<Messager> messagers = new ArrayList<>();
 
-    public TerminalManager(TextView terminalView, EditText inputView, TextView prefixView, TextView submitView, SkinManager skinManager,
-                           String hint, boolean inputUp) {
+    public TerminalManager(TextView terminalView, EditText inputView, TextView prefixView, TextView submitView, SkinManager skinManager, String hint, boolean inputUp) {
         if (terminalView == null || inputView == null || prefixView == null || skinManager == null)
             throw new UnsupportedOperationException();
 
@@ -115,7 +115,7 @@ public class TerminalManager {
             @Override
             public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
 
-//                physical enter is temporary ignores
+//                physical enter is temporary ignored
                 if (actionId == EditorInfo.IME_ACTION_GO || actionId == EditorInfo.IME_ACTION_DONE) {
                     onNewInput();
                     return true;
@@ -132,8 +132,8 @@ public class TerminalManager {
     private void setupNewInput() {
         mInputView.setText(Tuils.EMPTYSTRING);
 
-        mCurrentOutputId++;
-        globalId++;
+//        mCurrentOutputId++;
+//        globalId++;
 
         requestInputFocus();
     }
@@ -148,6 +148,8 @@ public class TerminalManager {
         }
         writeToView(PREFIX + input, INPUT);
 
+        cmds++;
+
         if (mInputListener != null) {
             mInputListener.onNewInput(input);
         }
@@ -157,77 +159,96 @@ public class TerminalManager {
         return true;
     }
 
-    public void setOutput(String output, int id) {
+    public void setOutput(String output) {
         if (output == null)
             return;
 
-        writeToView(output, OUTPUT, id);
+        if(output.equals(clear.CLEAR)) {
+            clear();
+            return;
+        }
+
+        writeToView(output, OUTPUT);
 
         int counter = 0;
         for(Messager messager : messagers) {
-            if(globalId != 0 && globalId % messager.n == 0) {
+            if(cmds != 0 && cmds % messager.n == 0) {
                 counter++;
-                writeToView(messager.message, OUTPUT, ++mCurrentOutputId);
+                writeToView(messager.message, OUTPUT);
             }
         }
-        globalId += counter;
 
         scrollToEnd();
     }
 
-    public void writeToView(String text, int type) {
-        writeToView(text, type, mCurrentOutputId);
-    }
+//    private void writeToView(final String text, final int type, int id) {
+//        Log.e("andre", "0");
+////        this is for when an input or a std (synchronous) output happens
+//        if(type == INPUT || id >= mCurrentOutputId) {
+//            Log.e("andre", "1");
+//            if(Looper.myLooper() == Looper.getMainLooper()) {
+//                if(!mTerminalView.getText().toString().endsWith(Tuils.NEWLINE)) {
+//                    mTerminalView.append(Tuils.NEWLINE);
+//                }
+//                mTerminalView.append(getSpannable(text, type));
+//            } else {
+//                ((Activity) mTerminalView.getContext()).runOnUiThread(new Runnable() {
+//                    @Override
+//                    public void run() {
+//                        if(!mTerminalView.getText().toString().endsWith(Tuils.NEWLINE)) {
+//                            mTerminalView.append(Tuils.NEWLINE);
+//                        }
+//                        mTerminalView.append(getSpannable(text, type));
+//                    }
+//                });
+//            }
+//        }
+////        this is for when a delayed output happens
+//        else if(type == OUTPUT) {
+//            Log.e("andre", "2");
+//            List<String> oldText = getLines(mTerminalView);
+//            List<Map.Entry<String, String>> wrappedOldText = splitInputOutput(oldText);
+//
+//            if(wrappedOldText.size() > id) {
+//                Log.e("andre", "3");
+//                SimpleMutableEntry selectedEntry = (SimpleMutableEntry) wrappedOldText.get(id);
+//                selectedEntry.setValue(getSpannable(text, type));
+//
+//                final List<String> newText = toFlatList(wrappedOldText);
+//
+//                ((Activity) mTerminalView.getContext()).runOnUiThread(new Runnable() {
+//                    @Override
+//                    public void run() {
+//                        mTerminalView.setText(Tuils.EMPTYSTRING);
+//                        for(CharSequence sequence : newText) {
+//                            sequence = Tuils.trimWhitespaces(sequence);
+//                            if(isInput(sequence)) {
+//                                mTerminalView.append(Tuils.NEWLINE);
+//                                mTerminalView.append(getSpannable(sequence.toString(), INPUT));
+//                                mTerminalView.append(Tuils.NEWLINE);
+//                            } else {
+//                                mTerminalView.append(getSpannable(sequence.toString(), OUTPUT));
+//                            }
+//                        }
+//                    }
+//                });
+//            } else {
+//                Log.e("andre", "4");
+//            }
+//        }
+//    }
+
+    private void writeToView(final String text, final int type) {
+        mTerminalView.post(new Runnable() {
+            @Override
+            public void run() {
+                String txt = text;
+                txt = Tuils.NEWLINE.concat(txt);
 
-    private void writeToView(final String text, final int type, int id) {
-//        this is for when an input or a std (synchronous) output happens
-        if(type == INPUT || id >= mCurrentOutputId) {
-            if(Looper.myLooper() == Looper.getMainLooper()) {
-                if(!mTerminalView.getText().toString().endsWith(Tuils.NEWLINE)) {
-                    mTerminalView.append(Tuils.NEWLINE);
-                }
-                mTerminalView.append(getSpannable(text, type));
-            } else {
-                ((Activity) mTerminalView.getContext()).runOnUiThread(new Runnable() {
-                    @Override
-                    public void run() {
-                        if(!mTerminalView.getText().toString().endsWith(Tuils.NEWLINE)) {
-                            mTerminalView.append(Tuils.NEWLINE);
-                        }
-                        mTerminalView.append(getSpannable(text, type));
-                    }
-                });
-            }
-        }
-//        this is for when a delayed output happens
-        else if(type == OUTPUT) {
-            List<String> oldText = getLines(mTerminalView);
-            List<Map.Entry<String, String>> wrappedOldText = splitInputOutput(oldText);
-
-            if(wrappedOldText.size() > id) {
-                SimpleMutableEntry selectedEntry = (SimpleMutableEntry) wrappedOldText.get(id);
-                selectedEntry.setValue(getSpannable(text, type));
-
-                final List<String> newText = toFlatList(wrappedOldText);
-
-                ((Activity) mTerminalView.getContext()).runOnUiThread(new Runnable() {
-                    @Override
-                    public void run() {
-                        mTerminalView.setText(Tuils.EMPTYSTRING);
-                        for(CharSequence sequence : newText) {
-                            sequence = Tuils.trimWhitespaces(sequence);
-                            if(isInput(sequence)) {
-                                mTerminalView.append(Tuils.NEWLINE);
-                                mTerminalView.append(getSpannable(sequence.toString(), INPUT));
-                                mTerminalView.append(Tuils.NEWLINE);
-                            } else {
-                                mTerminalView.append(getSpannable(sequence.toString(), OUTPUT));
-                            }
-                        }
-                    }
-                });
+                SpannableString string = getSpannable(txt, type);
+                mTerminalView.append(string);
             }
-        }
+        });
     }
 
     public void simulateEnter() {
@@ -284,7 +305,7 @@ public class TerminalManager {
         } else {
             return null;
         }
-        spannableString.setSpan(new ForegroundColorSpan(color), 0, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+        spannableString.setSpan(new ForegroundColorSpan(color), 0, spannableString.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
         return spannableString;
     }
 
@@ -340,17 +361,17 @@ public class TerminalManager {
         return mInputView;
     }
 
-    public int getCurrentOutputId() {
-        return mCurrentOutputId;
-    }
-
     public void clear() {
-        ((Activity) mTerminalView.getContext()).runOnUiThread(new Runnable() {
+        mTerminalView.post(new Runnable() {
             @Override
             public void run() {
                 mTerminalView.setText(Tuils.EMPTYSTRING);
+            }
+        });
+        mInputView.post(new Runnable() {
+            @Override
+            public void run() {
                 mInputView.setText(Tuils.EMPTYSTRING);
-                mCurrentOutputId = 0;
             }
         });
     }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/CommandExecuter.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/CommandExecuter.java
index 0533c4a8930febd2df8cdb238a3f9cec6f0637e3..95f3ea60e8fc4805035a97a2a0b9fb48407d257a 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/CommandExecuter.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/CommandExecuter.java
@@ -5,5 +5,5 @@ package ohi.andre.consolelauncher.tuils.interfaces;
  */
 public interface CommandExecuter {
 
-    String exec(String input, int id);
+    String exec(String input);
 }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/Outputable.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/Outputable.java
index aa905636117c1e86e48b048f45e0f8b7c4f7e8d7..940a5c173e740852cc5ee93c7e3dd5be72ee3f3a 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/Outputable.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/Outputable.java
@@ -4,5 +4,5 @@ package ohi.andre.consolelauncher.tuils.interfaces;
  * Created by andre on 25/07/15.
  */
 public interface Outputable {
-    void onOutput(String output, int id);
+    void onOutput(String output);
 }
diff --git a/app/src/main/res/raw/settings.txt b/app/src/main/res/raw/settings.txt
index e27a0c403050ed7dede0fab01bd0e5a74ab22d8b..1b72c360c9410fdffc063b11743ea85edc514917 100755
--- a/app/src/main/res/raw/settings.txt
+++ b/app/src/main/res/raw/settings.txt
@@ -1,5 +1,5 @@
 // do not edit the settingsVersion property!
-settingsVersion=4.11
+settingsVersion=4.10
 
 // when you are ready go back to t-ui and type "restart" to see changes
 
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index d6002921d941941679be1426b61835fec5e273a7..fdddff0f0196d52999d4ab0cf772d366fe279847 100755
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -9,10 +9,10 @@
     <string name="permissions_toast">You have to grant Storage permission at least</string>
     <string name="version_label">Version:</string>
 
-    <string name="rate_donate_text">Do you like my app? Rate T-UI on Play Store (command: >>rate) or offer me a coffee (command: >>donate)</string>
+    <string name="rate_donate_text">\nDo you like T-UI? Rate T-UI on Play Store (command: >>rate) or offer me a coffee (command: >>donate).\n\nYou can disable this message with >>tuisettings</string>
 
     <!-- app mgr -->
-    <string name="output_appnotfound">Application or package not found</string>
+    <string name="output_appnotfound">Application not found</string>
     <string name="output_hideapp">state: hidden</string>
     <string name="output_unhideapp">state: shown</string>
 
@@ -42,9 +42,10 @@
     <!-- phone -->
     <string name="output_wifi">WiFi active:</string>
     <string name="output_data">Mobile Data active:</string>
+    <string name="output_bluetooth">Bluetooth active:</string>
+    <string name="output_airplane">Airplane Mode active:</string>
     <string name="output_numbernotfound">Contact not found</string>
     <string name="output_nofeature">Can\'t use this feature on your Android version</string>
-    <string name="output_airplane">Airplane Mode active:</string>
 
     <!-- files -->
     <string name="output_isfile">Cant\'t write here. It\'s a file</string>
@@ -56,8 +57,9 @@
     <string name="output_opening">Opening file:</string>
 
     <!-- install/uninstall -->
-    <string name="output_uninstalling">Uninstall triggered:</string>
+    <string name="output_uninstalling">Uninstall:</string>
     <string name="output_removetui">Uninstalling t-ui</string>
+    <string name="app_installed">App installed:</string>
 
     <!-- music -->
     <string name="output_playing">Playing:</string>
@@ -84,10 +86,10 @@
     <string name="wifi">WiFi:</string>
 
     <!-- infos -->
-    <string name="output_about">Francesco Andreuzzi, ITA, Programmer, andreuzzi.francesco@gmail.com
-        \n\nLuke Winward, USA, Designer
-        \n\nOpen Source Libraries:
-        \nandre1299-comparestring
+    <string name="output_about">Francesco Andreuzzi (Italy)\n\t-> andreuzzi.francesco@gmail.com
+        \n\nLuke Winward, Design &amp; Testing
+        \n\n\nOpen Source Libraries:
+        \n(Francesco Andreuzzi) - CompareString
         \nApache commons-io
     </string>
     <string name="output_refresh">Refreshed: apps and alias</string>
@@ -109,6 +111,7 @@
         \n\nExample:
         \napps -h whatsapp
     </string>
+    <string name="help_bluetooth">Toggle Bluetooth</string>
     <string name="help_clear">Clear the screen</string>
     <string name="help_call">Perform a call to someone or get contacts;
         \nUsage: call number OR name