User Tools

Site Tools


script_autosetupappfreeze

====== Differences ====== This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
script_autosetupappfreeze [2016/12/17 18:59]
cdfa 1.8.3
script_autosetupappfreeze [2017/07/21 08:57] (current)
cdfa 1.8.4
Line 4: Line 4:
   * Initial request: https://​plus.google.com/​+JaroslavGrochal/​posts/​BDKDMrTMfxt   * Initial request: https://​plus.google.com/​+JaroslavGrochal/​posts/​BDKDMrTMfxt
   * GitHub: https://​github.com/​cdfa/​AutoSetupLongTapFreeze   * GitHub: https://​github.com/​cdfa/​AutoSetupLongTapFreeze
-  * Version: 1.8.3+  * Version: 1.8.4
  
 ====== How to use the script ====== ====== How to use the script ======
Line 43: Line 43:
   * Added freezeing/​unfreezing all item from menu   * Added freezeing/​unfreezing all item from menu
   * Added long press folder to freeze/​unfreeze all items in it   * Added long press folder to freeze/​unfreeze all items in it
 +
 +1.8.4
 +  * Ask to unfreeze and run an item if it is frozen instead of saying that the app is not installed
  
 ====== Script code ====== ====== Script code ======
Line 50: Line 53:
   // for Sources see: http://​www.lightninglauncher.com/​scripting/​reference/​api/​reference/​net/​pierrox/​lightning_launcher/​script/​api/​Event.html   // for Sources see: http://​www.lightninglauncher.com/​scripting/​reference/​api/​reference/​net/​pierrox/​lightning_launcher/​script/​api/​Event.html
   // for Events see http://​www.lightninglauncher.com/​scripting/​reference/​api/​reference/​net/​pierrox/​lightning_launcher/​script/​api/​PropertySet.html   // for Events see http://​www.lightninglauncher.com/​scripting/​reference/​api/​reference/​net/​pierrox/​lightning_launcher/​script/​api/​PropertySet.html
-  // you may only have to set 1 in the future. 
   , freezeSource = "​I_LONG_CLICK"​   , freezeSource = "​I_LONG_CLICK"​
   , freezeEvent = "​i.longTap";​   , freezeEvent = "​i.longTap";​
Line 56: Line 58:
 bindClass("​android.widget.Toast"​);​ bindClass("​android.widget.Toast"​);​
 bindClass("​android.content.pm.PackageManager"​);​ bindClass("​android.content.pm.PackageManager"​);​
-bindClass('java.lang.Runtime'​);+bindClass("java.lang.Thread"​);​ 
 +bindClass("​android.os.Handler"​);​ 
 +bindClass("​android.os.Looper"​);
 bindClass('​java.io.BufferedReader'​);​ bindClass('​java.io.BufferedReader'​);​
 bindClass('​java.io.InputStreamReader'​);​ bindClass('​java.io.InputStreamReader'​);​
 bindClass('​java.io.DataOutputStream'​);​ bindClass('​java.io.DataOutputStream'​);​
 bindClass('​java.lang.StringBuffer'​);​ bindClass('​java.lang.StringBuffer'​);​
-bindClass("java.lang.Runnable"​);​ +bindClass('java.lang.Runtime'​);
-bindClass("​java.lang.Thread"​);​ +
-bindClass("​android.os.Handler"​);​ +
-bindClass("​android.os.Looper"​);+
  
 var script = getCurrentScript() var script = getCurrentScript()
Line 103: Line 104:
     c.setTag("​longTapFreeze",​ false);     c.setTag("​longTapFreeze",​ false);
     restoreEventHandler(c,​ freezeEvent);​     restoreEventHandler(c,​ freezeEvent);​
 +    restoreEventHandler(c,​ '​i.tap'​);​
     restoreEventHandler(c,​ "​i.menu"​);​     restoreEventHandler(c,​ "​i.menu"​);​
     restoreEventHandler(c,​ "​menu"​);​     restoreEventHandler(c,​ "​menu"​);​
-    if(c.getTag("​autosync"​) == "​true"​) restoreEventHandler(c,​ "​resumed"​);​+    if(c.getTag("​autosync"​) ​=== "​true"​) restoreEventHandler(c,​ "​resumed"​);​
     c.getAllItems().forEach(function(it){     c.getAllItems().forEach(function(it){
       if(isFrozen(it))       if(isFrozen(it))
Line 113: Line 115:
     cs.forEach(function(c){     cs.forEach(function(c){
       var opener;       var opener;
-      if((opener = c.getOpener()) && opener.getType() == "​Folder"​){+      if((opener = c.getOpener()) && opener.getType() ​=== "​Folder"​){
         if(isFrozen(opener))         if(isFrozen(opener))
           unfreezeEffect(opener);​           unfreezeEffect(opener);​
Line 121: Line 123:
 } }
  
 +/**
 + * Checks if an object is an array.
 + * @param object
 + * @returns {boolean}
 + */
 function isArray(object){ function isArray(object){
-  return Object.prototype.toString.call(object) == '​[object Array]';​+  return Object.prototype.toString.call(object) ​=== '​[object Array]';​
 } }
  
-/* +/*
- ATTENTION: + * If this function is executed in a thread that is the main GUI thread, execute func, or else execute func in the main GUI thread. (Android doesn'​t like it when you change the GUI outside of the main GUI thread) 
- ​if ​multiple commands are executed as root, the output ​will be an array of the returned ​lines + * @param func {function} 
- if multiple commands are not executed as rootthe output will be an array of returned outputs (which are themselves arrays of lines)+ */ 
 +function handleGUIEdit(func){ 
 +  ​if(Looper.getMainLooper().getThread() === Thread.currentThread()){ 
 +    func(); 
 +  }else{ 
 +    GUIHandler.post(func);​ 
 +  } 
 +
 + 
 +/** 
 + * Starts a new background thread with func. 
 + * @param func {function} - The function the thread executes. 
 + */ 
 +function startNewBackgroundThread(func){ 
 +  var thread = new Thread(function(){ 
 +    func(); 
 +    // if a looper was initialized in funcmake sure the thread can die by stopping the thread when the Looper idles. 
 +    if(threads[Thread.currentThread().getId()].prepared === true){ 
 +      Looper.myLooper().getQueue().addIdleHandler(function(){ 
 +        Looper.myLooper().quitSafely();​ 
 +      }); 
 +      Looper.loop();​ 
 +    } 
 +  }); 
 +  thread.setUncaughtExceptionHandler(function(th,​ ex){ 
 +    handleGUIEdit(function(){ 
 +      alert(ex.getMessage());​ 
 +    }) 
 +  }); 
 +  threads[thread.getId()] = {}; 
 +  thread.start();​ 
 +
 + 
 +//​noinspection JSValidateJSDoc 
 +/** 
 + * Gets a handler for the current thread and initializes a looper if necessary. 
 + * @returns {Handler} 
 + */ 
 +function getHandler(){ 
 +  if(Looper.getMainLooper().getThread() === Thread.currentThread()){ 
 +    return GUIHandler;​ 
 +  }else{ 
 +    var threadId = Thread.currentThread().getId();​ 
 +    if(threads[threadId].prepared !== true){ 
 +      Looper.prepare();​ 
 +      threads[threadId].prepared = true; 
 +    } 
 +    return new Handler();​ 
 +  } 
 +
 + 
 +/** 
 + * This callback ​will be called when the executing of the command(s) is finished 
 + * 
 + * @callback finishedCallback 
 + * @param {string[]} An array of the lines the command(s) returned 
 + */ 
 +/** 
 + * This callback will be called when a command is executed. 
 + * 
 + * @callback executedCallback 
 + */ 
 +/** 
 + * Runs a command in the terminal 
 + * @param cmds {string|string[]} - The command or array of commmands to be executed. 
 + * @param [asRoot=false] {boolean} - If the command(s) should be executed as root or not. 
 + * @param [newThread=true] {boolean} - If the executing of commands should happen in a new thread or not. (useful for root commands) 
 + * @param [callback] {finishedCallback} - The callback that handles ​the output
 + * @param [onExecuted] {executedCallback} - A callback that will be called when a command is executed. useful for multiple commands that take some time) 
 + * @returns {string[]||string[][]} - (only if asRoot == false && newThread == false) Returns ​an array of the lines written in the terminal or an array of arrays if multiple commands were executed.
  */  */
 function runCmd(cmds,​ asRoot, newThread, callback, onExecuted){ function runCmd(cmds,​ asRoot, newThread, callback, onExecuted){
Line 134: Line 210:
     , output, process, reader, writer;     , output, process, reader, writer;
  
 +  // set optional arguments
 +  if(newThread !== false)
 +    newThread = true;
 +
 +  /**
 +   * Helper function for executing the command(s). Gets its parameters from the parent function.
 +   * @returns {string[]||string[][]} - (only if asRoot == false && newThread == false) Returns an array of the lines written in the terminal or an array of arrays if multiple commands were executed.
 +   */
   function execCmd(){   function execCmd(){
 +    /**
 +     * Checks if the command is a string and if not alerts the user.
 +     * @param cmd {string}
 +     * @returns {boolean}
 +     */
     function checkCmd(cmd){     function checkCmd(cmd){
       if(typeof(cmd) === "​string"​){       if(typeof(cmd) === "​string"​){
Line 145: Line 234:
     }     }
  
 +    //​noinspection JSValidateJSDoc
 +    /**
 +     * Actually executes command.
 +     * @param cmd {string}
 +     * @param writer {DataOutputStream} - The writer to write the command to.
 +     * @returns {boolean} If the command was actually written or not.
 +     */
     function exec(cmd, writer){     function exec(cmd, writer){
       if(checkCmd(cmd)){       if(checkCmd(cmd)){
Line 154: Line 250:
     }     }
  
 +    //​noinspection JSValidateJSDoc
 +    /**
 +     * Read the output from the reader.
 +     * @param reader {BufferedReader}
 +     * @returns {Array} An array of lines that were outputted by the
 +     */
     function readOutput(reader){     function readOutput(reader){
       var tmp, output = [];       var tmp, output = [];
-      while((tmp = reader.readLine()) != null)+      while((tmp = reader.readLine()) !== null)
         output.push(tmp);​         output.push(tmp);​
  
-      return output.length == 1 ? output[0] : output;+      return output.length ​=== 1 ? output[0] : output;
     }     }
  
 +    /**
 +     * Executes the callback and if the callback is not a function alerts the user.
 +     * @param callback
 +     * @param output {Array} - The argument that is passed to the callback
 +     */
     function handleCallback(callback,​ output){     function handleCallback(callback,​ output){
-      if(typeof callback == "​function"​){+      if(typeof callback ​=== "​function"​){
         handler.post(function(){         handler.post(function(){
           callback(output);​           callback(output);​
Line 245: Line 352:
     throw new Error("​Multiple callbacks are not possible in su mode. Use onExecuteds instead."​);​     throw new Error("​Multiple callbacks are not possible in su mode. Use onExecuteds instead."​);​
  
-  if(newThread ​=== false)+  if(newThread){
-    return execCmd();​ +
-  }else{+
     startNewBackgroundThread(function(){     startNewBackgroundThread(function(){
       execCmd();       execCmd();
-    })+    })
 +  }else{ 
 +    return execCmd();
   }   }
 } }
Line 266: Line 373:
     return false;     return false;
  
-  var onBlackList = falseonWhiteList;​ +  var onWhiteList
-  ​for(var i 0; i < blackList.length; i++){ +    ​onBlackList ​= blackList.some(function(pkg){ 
-    if(pkgName == blackList[i]){ +      ​return pkg === pkgName
-      ​onBlackList ​true; +    });
-      break+
-    } +
-  }+
  
-  if(whiteList.length == 0){+  if(whiteList.length ​=== 0){
     onWhiteList = true;     onWhiteList = true;
   }else{   }else{
-    onWhiteList = false; +    onWhiteList = whiteList.some(function(pkg){ 
-    for(var i = 0; i < whiteList.length; i++){ +      ​return pkg === pkgName
-      ​if(pkgName ​== whiteList[i]){ +    });
-        onWhiteList ​true; +
-        break; +
-      } +
-    }+
   }   }
  
Line 302: Line 402:
 } }
  
-function freeze(it){ +function freeze(it, callback){ 
-  if(it.getType() == "​Folder"​){+  if(it.getType() ​=== "​Folder"​){
     freezeContainer(it.getContainer());​     freezeContainer(it.getContainer());​
   }else{   }else{
Line 309: Line 409:
       runCmd("​pm disable " + pkgName, true, true, null, function(){       runCmd("​pm disable " + pkgName, true, true, null, function(){
         freezeEffect(it);​         freezeEffect(it);​
 +        if(typeof callback === '​function'​)
 +          callback();
       });       });
     });     });
Line 314: Line 416:
 } }
  
-function unfreeze(it){ +function unfreeze(it, callback){ 
-  if(it.getType() == "​Folder"​){+  if(it.getType() ​=== "​Folder"​){
     unfreezeContainer(it.getContainer());​     unfreezeContainer(it.getContainer());​
   }else{   }else{
Line 321: Line 423:
       runCmd("​pm enable " + pkgName, true, true, null, function(){       runCmd("​pm enable " + pkgName, true, true, null, function(){
         unfreezeEffect(it);​         unfreezeEffect(it);​
 +        if(typeof callback === '​function'​)
 +          callback();
       });       });
     });     });
Line 338: Line 442:
 function batchFreezeAction(items,​ action, callback){ function batchFreezeAction(items,​ action, callback){
   var frozenStateChecker,​ cmd, effect;   var frozenStateChecker,​ cmd, effect;
-  if(action == "​freeze"​){+  if(action ​=== "​freeze"​){
     frozenStateChecker = function(it){ return !isFrozen(it);​ };     frozenStateChecker = function(it){ return !isFrozen(it);​ };
     cmd = "pm disable ";     cmd = "pm disable ";
     effect = function(it){ freezeEffect(it);​ }     effect = function(it){ freezeEffect(it);​ }
-  }else if(action == "​unfreeze"​){+  }else if(action ​=== "​unfreeze"​){
     frozenStateChecker = function(it){ return isFrozen(it);​ };     frozenStateChecker = function(it){ return isFrozen(it);​ };
     cmd = "pm enable ";     cmd = "pm enable ";
Line 360: Line 464:
   });   });
  
-  if(cmds.length != 0){+  if(cmds.length !== 0){
     var counter = 0;     var counter = 0;
     runCmd(cmds,​ true, true, function(){     runCmd(cmds,​ true, true, function(){
Line 375: Line 479:
   cs.forEach(function(c){   cs.forEach(function(c){
     var opener;     var opener;
-    if((opener = c.getOpener()) && opener.getType() == "​Folder"​)+    if((opener = c.getOpener()) && opener.getType() ​=== "​Folder"​)
       effect(opener);​       effect(opener);​
   });   });
Line 393: Line 497:
  
 function isFrozen(it){ function isFrozen(it){
-  return it.getTag("​frozen"​) == "true";+  return it.getTag("​frozen"​) === 'true';
 } }
  
 function getFrozenApps(){ function getFrozenApps(){
-  if(frozenApps == null){+  if(typeof ​frozenApps === '​undefined'​){
     frozenApps = [];     frozenApps = [];
     var pkgs = runCmd("​pm list packages -d", false, false);     var pkgs = runCmd("​pm list packages -d", false, false);
Line 418: Line 522:
 function syncItem(it){ function syncItem(it){
   var frozenApps = getFrozenApps();​   var frozenApps = getFrozenApps();​
-  if(it.getType() == "​Shortcut"​){+  if(it.getType() ​=== "​Shortcut"​){
     var pkgName = getPackageName(it);​     var pkgName = getPackageName(it);​
     if(pkgName && isFreezable(pkgName)){     if(pkgName && isFreezable(pkgName)){
-      var isFrozen = it.getTag("​frozen"​) == "true";+      var isFrozen = it.getTag("​frozen"​) === 'true';
       var matched = frozenApps.some(function(pkg){       var matched = frozenApps.some(function(pkg){
-        return pkg == pkgName;+        return pkg === pkgName;
       });       });
       if(!isFrozen && matched){       if(!isFrozen && matched){
Line 438: Line 542:
 } }
  
-function handleGUIEdit(func){ +if(typeof getEvent !== "​undefined"​){
-  if(Looper.getMainLooper().getThread() == Thread.currentThread()){ +
-    func(); +
-  }else{ +
-    GUIHandler.post(func);​ +
-  } +
-+
- +
-function startNewBackgroundThread(func){ +
-  var thread = new Thread(function(){ +
-    func(); +
-    if(threads[Thread.currentThread().getId()].prepared == true){ +
-      Looper.myLooper().getQueue().addIdleHandler(function(){ +
-        Looper.myLooper().quitSafely();​ +
-      }); +
-      Looper.loop();​ +
-    } +
-  }); +
-  thread.setUncaughtExceptionHandler(function(th,​ ex){ +
-    handleGUIEdit(function(){ +
-      alert(ex.getMessage());​ +
-    }); +
-  }); +
-  threads[thread.getId()] = {}; +
-  thread.start();​ +
-+
- +
-function getHandler(){ +
-  if(Looper.getMainLooper().getThread() == Thread.currentThread()){ +
-    return GUIHandler;​ +
-  }else{ +
-    var threadId = Thread.currentThread().getId();​ +
-    if(threads[threadId].prepared != true){ +
-      Looper.prepare();​ +
-      threads[threadId].prepared = true; +
-    } +
-    return new Handler();​ +
-  } +
-+
- +
-if(typeof getEvent != "​undefined"​){+
   var c   var c
     , e = getEvent()     , e = getEvent()
Line 484: Line 548:
     , data = e.getData();​     , data = e.getData();​
   if(data){   if(data){
-    if(data == "​sync"​){+    if(data ​=== "​sync"​){
       if(c = e.getContainer()){       if(c = e.getContainer()){
         syncContainer(c);​         syncContainer(c);​
Line 490: Line 554:
         throw new Error("​Could not find a way to determine the container to sync. Run the script from an item in the container or from the container itself or add the container id directly afrer '​sync'​."​)         throw new Error("​Could not find a way to determine the container to sync. Run the script from an item in the container or from the container itself or add the container id directly afrer '​sync'​."​)
       }       }
-    }else if(data.substring(0,​ 4) == "​sync"​){+    }else if(data.substring(0,​ 4) === "​sync"​){
       var cId = data.substring(4,​ data.length);​       var cId = data.substring(4,​ data.length);​
       c = screen.getContainerById(cId);​       c = screen.getContainerById(cId);​
Line 500: Line 564:
       c = e.getContainer();​       c = e.getContainer();​
       cId = c.getId();       cId = c.getId();
-      if(c.getTag("​longTapFreeze"​) == "​true"​){+      if(c.getTag("​longTapFreeze"​) ​=== "​true"​){
         if(confirm("​Are you sure you want to uninstall?"​)){         if(confirm("​Are you sure you want to uninstall?"​)){
           uninstall(c);​           uninstall(c);​
Line 509: Line 573:
           c.setTag("​longTapFreeze",​ true);           c.setTag("​longTapFreeze",​ true);
           setEventHandlerRestorably(c,​ freezeEvent,​ EventHandler.RUN_SCRIPT,​ script.getId());​           setEventHandlerRestorably(c,​ freezeEvent,​ EventHandler.RUN_SCRIPT,​ script.getId());​
 +          setEventHandlerRestorably(c,​ '​i.tap',​ EventHandler.RUN_SCRIPT,​ script.getId());​
           setEventHandlerRestorably(c,​ "​i.menu",​ EventHandler.RUN_SCRIPT,​ script.getId());​           setEventHandlerRestorably(c,​ "​i.menu",​ EventHandler.RUN_SCRIPT,​ script.getId());​
           setEventHandlerRestorably(c,​ "​menu",​ EventHandler.RUN_SCRIPT,​ script.getId());​           setEventHandlerRestorably(c,​ "​menu",​ EventHandler.RUN_SCRIPT,​ script.getId());​
Line 520: Line 585:
       }       }
     }else{     }else{
-      //long tap 
       var src = e.getSource();​       var src = e.getSource();​
-      if(src == freezeSource){+      if(src ​=== freezeSource){
         if(isFrozen(it)){         if(isFrozen(it)){
           unfreeze(it);​           unfreeze(it);​
Line 528: Line 592:
           freeze(it);           freeze(it);
         }         }
 +      }else if(src === '​I_CLICK'​){
 +        if( isFrozen(it) && confirm("​Unfreeze and run?"​))
 +          unfreeze(it,​ function(){
 +            it.launch();​
 +          });
 +        else
 +          it.launch();​
       }       }
     }     }
Line 533: Line 604:
 }else if(menu){ }else if(menu){
   var mode = menu.getMode();​   var mode = menu.getMode();​
-  if(mode == Menu.MODE_ITEM_SUBMENU_ACTION || mode == Menu.MODE_ITEM_NO_EM){+  if(mode ​=== Menu.MODE_ITEM_SUBMENU_ACTION || mode === Menu.MODE_ITEM_NO_EM){
     menu.addMainItem("​Sync frozen-state",​ function(){     menu.addMainItem("​Sync frozen-state",​ function(){
       syncItem(item);​       syncItem(item);​
       menu.close();​       menu.close();​
     });     });
-  }else if(mode == Menu.MODE_CONTAINER_SUBMENU_ITEMS){+  }else if(mode ​=== Menu.MODE_CONTAINER_SUBMENU_ITEMS){
     menu.addMainItem("​Sync frozen-state",​ function(){     menu.addMainItem("​Sync frozen-state",​ function(){
       syncContainer(container);​       syncContainer(container);​
script_autosetupappfreeze.txt · Last modified: 2017/07/21 08:57 by cdfa