LG VS840系统修改小工具 XposedLucidMod

废话

花两百从淘宝买了个LG VS840电信手机来玩,这手机性价比不错,双核,1G内存,8G存储,IPS硬屏.
有点郁闷的是原生系统默认是连接不上国内的电信网络打电话,需要修改设置里的选项才行.而此选项却隐藏起来,需要修改LGSettings.apk文件才能使用.

网上有修改好的LGSettings.apk文件,不过都是rom v8以前的版本,v9无法使用.
个人不喜欢替换原生系统的文件,用过一个不错的权限管理软件xprivacy,从而了解到xposed这个强大的rom修改框架,此框架修改rom无需要修改apk文件,大爱.

XposedLucidMod功能列表

  • 添加系统选择到设置
  • 从设置里删除Backup Assistant Plus
  • 从帐号与同步里删除VERIZON帐户选项
  • 删除状态栏的三角形漫游图标
  • 删除定位的十字架图标

效果图请看 http://pan.baidu.com/s/1sjzyceL

安装教程

XposedLucidMod源码

https://github.com/mangege/XposedLucidMod

待续

把LG VS840很多系统应用都精简掉了,还在测试稳定不,等稳定后会发布可精简应用列表.

在Linux用VirtualBox跑<自己动手写操作系统>示例一

在看于渊的<自己动手写操作系统>,第一章的示例用到软驱.
在这个年代,找到带软驱的计算机还真不容易,还好有虚拟机.

VirtualBox默认支持软驱镜像文件启动,难点在于在Linux环境创建软驱镜像并且把boot.bin写到镜像文件里.

本文基于archlinux环境操作,需要用到dd losetup mkfs.vfat等命令.
mkfs.vfat需要安装dosfstools这个包.

1 首先创建镜像文件

sudo dd if=/dev/zero of=/tmp/floppy.img bs=1k count=1440

2 格式化镜像文件

sudo mkfs.vfat /tmp/floppy.img

3 安装设备

sudo losetup losetup /dev/loop7 /tmp/floppy.img

4 复制启动文件

sudo dd if=boot.bin of=/dev/loop7 bs=512 count=1

5 删除设备

losetup -d /dev/loop7

6 设置VirtualBox的Floppy为"/tmp/floppy.img"文件

设置 -> 存储 -> 选择一个虚拟软盘

效果图 LinuxVBoxFloppy

指定时间段运行cpuminer(Python)

利用空闲的内网服务器折腾litecoin,但这东西太耗CPU资源了,不方便白天运行.
所以有了如下的Python2脚本,指定时间段运行cpuminer, 定时启动与关闭cpuminer.

import shlex
from datetime import datetime, time
import time as atime
from subprocess import Popen
from subprocess import call as pcall

BEGIN_HOUR = 18
END_HOUR = 7
minerd_process = None


def run_minerd():
    command_line = ('sh -c "./minerd -o http://mine.pool-x.eu:8337/'
                    ' -O cxh116.public:x -t 6 >> l.log 2>&1"')
    args = shlex.split(command_line)
    global minerd_process
    minerd_process = Popen(args)


def check_time():
    begin_time = time(BEGIN_HOUR)
    end_time = time(END_HOUR)
    current_time = datetime.now().time()
    if BEGIN_HOUR > END_HOUR:
        if current_time > begin_time or current_time < end_time:
            return True
        else:
            return False
    else:
        if current_time > begin_time and current_time < end_time:
            return True
        else:
            return False


def start():
    global minerd_process
    if check_time() and (minerd_process is None):
        run_minerd()


def stop():
    global minerd_process
    if (not check_time()) and (minerd_process is not None):
        if minerd_process.poll() is None:
            minerd_process.kill()
            pcall(['pkill', '-f', 'minerd'])
        minerd_process = None


def scheduler():
    while True:
        start()
        stop()
        atime.sleep(60*3)

scheduler()

定制SyntaxHighlighter工具栏

本文基于 SyntaxHighlighter 3.0.83 (July 02 2010)

工作需要简单的定制一下SyntaxHighlighter,在代码块首行显示代码的编程语言名.
效果:
SyntaxHighlighter

重点:

  • SyntaxHighlighter.toolbar.items.list此变量存放需要toolbar元素,默认有['expandSource', 'help']
  • 自定义toolbar元素可以参加官方的expandSource元素实现,主要要实现getHtml或execute方法.
    • getHtml返回值将会添加到页面div.toolbar
    • execute用于点击getHtml返回Html所执行的代码
    • 没有getHtml方法时,将会调用defaultGetHtml要方法
官方的expandSource代码
  expandSource: {
    getHtml: function(highlighter) {
      if (highlighter.getParam('collapse') != true) return '';

      var title = highlighter.getParam('title');
      return sh.toolbar.getButtonHtml(highlighter, 'expandSource', title ? title : sh.config.strings.expandSource);
    },

    execute: function(highlighter) {
      var div = getHighlighterDivById(highlighter.id);
      removeClass(div, 'collapsed');
    }
  }

如果有用到jQuery,把调用SyntaxHighlighter.all();你改成SyntaxHighlighter.highlight();应该是更好的选择,因为默认SyntaxHighlighter.all();是需要用的是window.onload,要等页面和图片都加载完才会调用SyntaxHighlighter.highlight();高亮;你可以改用$.ready
如果需要高亮页面后生成的html,也只要调用SyntaxHighlighter.highlight();即可

实现代码:
//自定义配置
function my_syntax_highlighter() {
  SyntaxHighlighter.config.stripBrs = true;
  SyntaxHighlighter.config.useScriptTags = false;
  SyntaxHighlighter.defaults.toolbar = true;
  SyntaxHighlighter.highlight();
}

//统一显示代码名,而不是显示brush name短名称
var human_code_names = {
  "ActionScript3": ["as3", "actionscript3"],
  "Assembly": ["nasm8086", "8086", "nasm", "asm", "masm"],
  "AppleScript": ["applescript"],
  "Bash/shell": ["bash", "shell"],
  "ColdFusion": ["cf", "coldfusion"],
  "C#": ["c-sharp", "csharp"],
  "C/C++": ["cpp", "c"],
  "CSS": ["css"],
  "Delphi/Pascal": ["delphi", "pas", "pascal"],
  "Diff/Patch": ["diff", "patch"],
  "Erlang": ["erl", "erlang"],
  "Groovy": ["groovy"],
  "JavaScript": ["js", "jscript", "javascript"],
  "Java": ["java"],
  "JavaFX": ["jfx", "javafx"],
  "Objective C": ["obj-c", "objc"],
  "Perl": ["perl", "pl"],
  "PHP": ["php"],
  "Plain Text": ["plain", "text"],
  "PowerShell": ["ps", "powershell"],
  "Python": ["py", "python"],
  "Ruby": ["rails", "ror", "ruby"],
  "Sass": ["sass", "scss"],
  "Scala": ["scala"],
  "SQL": ["sql"],
  "Visual Basic": ["vb", "vbnet"],
  "XML/HTML": ["xml", "xhtml", "xslt", "html", "xhtml"]
};

function human_code_name(brush_name) {
  brush_name = $.trim(brush_name);
  var result = null;
  $.each(human_code_names, function(key, value) {
    var hit_flag = false;
    $.each(value, function() {
      if (this == brush_name) {
        hit_flag = true;
        return false;
      }
    });
    if (hit_flag) {
      result = key;
      return false;
    }
  });

  if (result === null) return brush_name;
  else return result;
}

function custom_syntax_highlighter_toolbar() {
  SyntaxHighlighter.toolbar.items.list = ['codeName'];
  SyntaxHighlighter.toolbar.items.codeName = {
    getHtml: function(highlighter) {
      var brush_name = highlighter.params.brush;
      return '<span>' + human_code_name(brush_name) + ' code</span>';
    }
  };
}

$(function() {
  my_syntax_highlighter();
  syntax_highlighter_with_compatible();
});
样式:
div.syntaxhighlighter{
  overflow: auto;
}

.syntaxhighlighter .toolbar{
  width: 99.9% !important;
  height: 24px !important;
  line-height: 24px !important;
  background-color: whiteSmoke !important;
  font-weight: bold !important;
  text-indent: 6px !important;
  color: #333 !important;
  position: static !important;
  right: 0px !important;
  top: 0px !important;
}
.syntaxhighlighter .toolbar span{
  height: 24px !important;
  line-height: 24px !important;
}
.syntaxhighlighter table{
  border: solid 1px #DDD !important;
  padding: 5px 0 !important;
  width: 99.7% !important;
}

Jekyll高亮的另一个选择:JS高亮

Jekyll官方文档指导用户使用Liquid,再配合Pygments实现高亮,但作为markdown的忠实粉丝,怎么能用如此繁锁的语法.

Liquid代码块写法:


{% highlight ruby %}
def foo
  puts 'foo'
end
{% endhighlight %}

markdown GFM fenced code 代码块写法:

```ruby
def foo
  puts 'foo'
end
```

我相信你一眼就会爱上markdown的写法.

markdown高亮可以用Pygments,也可以用前台JS高亮,由于Jekyll使用redcarpet时定制Pygments高亮复杂度过高,所以我选择了简单的JS高亮.

需要用的到gem包版本

  • gem "jekyll", :git => 'git://github.com/chitsaou/jekyll.git', :branch => 'redcarpet-2.0', Jekyll 0.11.0版本不支持redcarpet 2.0以上,官方还没有合并此Pull Request
  • gem "redcarpet", "~> 2.1.1", 2.0以上才支持fenced code

修改Jekyll _config.yml

redcarpet:
  extensions: [fenced_code_blocks]
  render_options:

页面引入highlight.js,当然你也可以换成其它的javascript高亮库,但highlight.js支持自动检测语言,而且主题也多.

<link rel="stylesheet" href="http://yandex.st/highlightjs/7.1/styles/default.min.css">
<script src="http://yandex.st/highlightjs/7.1/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>

最后,调用Jekyll需要加--redcarpet参数,例如jekyll --redcarpet --server --auto.
如果问题,可以参考我的Jekyll配置, https://github.com/mangege/mangege

jQuery Validation定制:只有提交时才验证

jQuery Validation默认在失去光标会检测表单元素是否通过验证,没有通过的话则显示错误信息.
需求要求只有按提交才验证并显示错误信息.

jQuery Validation默认支持禁用失去光标时验证,一种简单的实现:

$("#commentForm").validate({onfocusout: false, onkeyup: false, onclick: false});

上面代码会引发一个问题,需要手动点击提交按钮才知道是否验证通过.比如有一个元素已经验证不通过,当我修改为正确的内容,需要再点击提交按钮才知道是否验证通过.
我们可以改成,当表单有未通过元素,失去光标等事件时自动验证表单元素.
最后变成,默认失去光标不会触发表单验证,点击提交按钮,如果表单未通过验证,这时修改表单内容失去光标会验证.

下面这种方式是一种无缝全局修改方式,在引入jQuery Validation的JS再引入此代码,之后直接调用$("#commentForm").validate()即可:

(function($) {

  var validator_defaults_dup = $.extend({}, $.validator.defaults);
  $.extend($.validator.defaults, {
    onfocusout: function() {
      if (this.numberOfInvalids() > 0) {
        validator_defaults_dup.onfocusout.apply(this, arguments);
      }
    },
    onkeyup: function() {
      if (this.numberOfInvalids() > 0) {
        validator_defaults_dup.onfocusout.apply(this, arguments);
      }
    },
    onclick: function() {
      if (this.numberOfInvalids() > 0) {
        validator_defaults_dup.onfocusout.apply(this, arguments);
      }
    }
  });


})(jQuery);

此方式不修改jQuery Validation源码,方便升级

一个由IE8'显示友好 http 错误信息'引起的BUG

使用jQuery Form Plugin上传文件,在IE8下会临时创建一个iframe用于form提交.而就是由这个iframe可能会引发两个BUG

显示文件下载对话框

当html response head的content type设置成IE不支持(没有关联处理程序)会像"application/octet-stream"二进制类型显示下载对话框.

解决办法: 设置content type为"text/plain",为了保险同时设置jQuery Form Plugin的dataType参数为你的正确类型.

response status 500时出错

重现这个Bug环境需要IE8,同时把浏览器设置"显示友好 http 错误信息"勾上.
另外当上传出错时,response的status设置为500,同时响应内容字节不能超过512字节.当内容小于512字节时,IE8会显示友好错误. https://github.com/malsup/form/issues/214#issuecomment-8189245 这样当错误提示内容小于512,同时选中显示友好http错误信息,上传正常出错时就会无法正常处理.

解决办法: 把错误主体内容用空白或其它字符填充,直大于512.例如Rails:
render :json => {:msg => 'error', :noop => ' '*512}, :status => 500, :content_type => Mime::TEXT

解决dwm6标题乱码

dwm标题不支持显示中文,打了pango补丁就能正常显示了

arch用户直接安装dwm-pango包 https://aur.archlinux.org/packages.php?ID=33193
不过貌似依赖很难编译

ubuntu用户从dwm官方下载源码包,再手动打pango补丁.

  • http://dwm.suckless.org/ 下载dwm6的源码包
  • https://aur.archlinux.org/packages.php?ID=33193 下载pango补丁
  • 解压dwm,再cd到其目录
  • 新开终端解压dwm-pango
  • 在dwm源码目录运行 patch -Np1 -i /tmp/dwm-pango/dwm-6.0-pango.patch, 注意把后面的patch文件路径改成你的
  • 补丁打完了按照自己的需要修改config.h,编译安装就行了
  • 也许需要手动apt-get安装libxinerama-dev和libpango1.0-dev信赖包

密云之行

上周日从四元桥骑行密云水库,地图计算出单程81KM,码表显示全程167KM.共花13个小时,中间就吃了次午饭.

这是买勇士560的第二次长途骑行,第一次是在网上认识了两朋友,五一小长假的第一天跑了一趟潭柘寺.
潭柘寺的G108路线还是比较有感觉,6公里的长坡,下坡的感觉太爽了.不过此路线车貌似比较多,路上还是得注意安全.

此次去密云水库是一个人,本来有一朋友在群里发起,但他在顺义,没有约到碰头的地方,后来想想就算了.
路线是直走G101,也就是京密路.路非常好走,没有一个坡.导致骑行都没有啥感觉.到时密云找水库时,才有点山路.
路上碰到一车队,有四五十岁的骑行去怀柔,有的骑的还是普通的通勤车.

好不容易到了终点,可以水库只能到山顶远远看望.景色还不错.

骑行达到人车合一的境界还差太远了.码表显示的平均时速是15KM/H,用的是前2后3的齿.骑行起来大腿不痛,但因为踏频还没有适合,第二天骑行时微微的感觉关节有点痛.
长距离的骑行感觉货架和骑行裤是很有必要的.背着背包肩膀痛.穿普通的裤子屁股痛,而且汗都湿了裤子,很不舒服.

高强度的运动对减肥还是很有效的,一次骑行下来,肚子上的脂肪都消耗的差不多了.

计划以后每周末都出行一次,为1000+公里的长途旅行做准备.

Ruby的Block与控制结构变量作用域小差别

在方法中,Block是新作用域,而控制结构还是方法的作用域.

def foo
  while true #控制结构
    i = 10
    break
  end
  puts i #正常输出10

  [1].map{ j = 100 }
  puts j #undefined local variable 错误 
end

foo