记录我是怎样把小米平板4(MIUI9.6)刷成开发板+获取root的

需求
实现一个app在小米平板4(MIUI9.6)上开机自动启动,如此而已。
然鹅,折腾的路确很长。

尝试一
作为一个半生熟的Android开发狗,那么开机启动一个app还不简单?我新建一个BootReceiver,我再申请权限android.permission.RECEIVE_BOOT_COMPLETED,我再声明Activity、Service、Intent什么的blablabla,整个流程做安卓开发的你一定不会不清楚,反正度娘是妥妥儿的告诉我。但是折腾完发现,无论如何就是不好死?开机app不启动,于是打开百度我会搜索这样的关键字“Android app 开机启动”,然后会找到这样的文章: https://blog.csdn.net/mmmccc000/article/details/52626075/ 其中你反复验证启动失败的原因:是不是Fast Boot模式?是不是权限添加的不对?是不是应用默认装到了sd卡里,我怎么样才能不装到sd卡而装到系统空间?各种各样的疑问,各种各样的尝试,但最后的结果就一个:还是不行。


尝试二
分割线分割前生,前生事此不再提,也就说使用开机广播那一套不知道是不行,还是还需要另外的协助?自省一下,前提条件是在小米平板4上装可以自动启动的app,那么小米平板4目前运行的是“MIUI9.6稳定版”,小米的系统肯定是深度定制版不知道有多深,但是小米可是有开发板的系统,是支持折腾的,那么问题来了,官网下载开发板地址是多少?此处内心独白:既然前面那套开机广播的脆脆弱弱(我自始至终都没有在模拟器上尝试,不知道为什么,可能是秀逗了),那么我可以不可以直接获取root权限,比如修改个init.d什么的直接就勾起我的Activity?脑回路有些大,但是没大胆就没大产不是。。。所以此处心里想的就是:开发板的系统自带肯定自带root权限,oh yes。。。
那刷小米的官方系统倒是很简单啊,直接设置里面手动选择安装包什么的就可以了,可是选来选取,刷来刷去我发现,账号依然不是root,adb连接到设备su依然不可用。

此处的插曲是,刷机之前需要解设备锁,也就是解锁BL(BootLoader),具体查看“更多设置” -> “开发者选项” -> “设备解锁状态“,如果因为下面这种情况卡住的话,告诉你只要在当前设备上换一个注册时间比较长,活跃度高的小米账号绑定设备,然后重新解锁就行。

请在此设备上登录该账号720小时后再尝试解锁该设备

 

迷茫时刻
可我真的记得有篇文章说的是小米开发板自带root,百度了N多文章,一天下来,脑子里什么都没有,全是这些内容,你只是个开发人员,你明白app生命周期,但系统原理你是无能为力的。要不淘宝上几十块刷一个吧,可是淘宝上问一下,有说能刷的,有说刷不了的。。。
屁不就刷个鸡?百度不行谷歌我还不行么。。。

尝试三 刷入TWRP
还是Google大法好,让我找到了这篇文章:《How to Install twrp Recovery Root XiaoMi Mi Pad 4》
文章清清爽爽,简单易懂,用到的几个文件清单如下,如果你不能下载的话,可以去这里:链接: https://pan.baidu.com/s/1NfYY2RRPmIwTILekDqv25w 提取码: zthz
1.TWRP 3.2 Xiaomi Mi Pad 4 对应Try.7z包里的recovery.img
2.SuperSu/Magisk
3.adb fast driver Try.7z包里没有这项,adb我觉得你自己能搞定
4.No-verity-opt-Entrypt
5.adb fastboot tools 参考3

参照着大神的文章,终于一步一步装上了TWRP,中间的过程如:

安装完成后手机是这样的,

 

然后adb shell进入设备,敲入su,发现$符号变成了#号才明白,root特么的成功了。

尝试四 怎么样把app安装到/system/app中
(以下操作在成功安装TWRP后进行)

既然机器已经root,那么我就可以乱来了是不是,我就可以直接
(以下操作在重启按住音量增大键+电源键进入TWRP后,选择Advanced->Terminal后进行,直接adb shell是没有vi等功能的)
1.vi init.d
2.GG 回车 a 回车 am start cc.lison.locked
3.Esc :wq
4.reboot
不好意思,轻度vim党,第二步的意思是翻到文件最后并加入am那句命令,然后保存重启,不好死,还是不好死,重启进入TWRP的Terminal发现刚才修改的init.d的内容没有了,改写的内容被覆盖掉了。。。怪不得一直提示我FileSystem read-only之类的,然后在TWRP中尝试文件管理器直接修改文件权限为755,还是不好死。。。又尝试了很多Magisk里的模块,不好死不好死。。。

尝试五
这一步尝试已经忘了搜索百度的什么关键字,总之是摸石头过河摸到了石头,详参这里:https://www.androidauthority.com/install-user-app-as-system-app-how-to-93522/
既然已经拿到了root权限,adb root + adb remount却不行,但是直接adb shell,然后切换su却可以(adb进入shell之后无法使用vi等工具),这是前提条件。于是又下载了一个ES 文件浏览器,安卓玩家对这个肯定不陌生,Magisk对其进行root授权(好像打开进入app就自动授权root权限),打开ES文件浏览器,把你要开机启动的app拷贝到/system/app目录,然后点击安装,世界就如此美好了。。。

PS。如果要删除安装在/system/app的app的话,只需要删除这个apk文件即可。

#文章做折腾过程记录,不对任何变砖与异常负责

BootstrapValidator 页面验证多个form

只做记录,没什么技术含量。

每个页面多个form,没问题,form id不同,name不同,然后“标识”不同,所谓标识就是放一个<input type=”hidden” 指定比如name=”type” ,那么多个form在action到同一个method的时候,就使用type判断当前提交的是哪个form;那bootstrapValidator里绑定的内容如下:

第一行jQuery选择器匹配所有form并添加bootstrapValidator,然后post时使用this传递form data,其他的form处理都一样,就四酱。

openshift配置http跳转https并且www域名跳转不带www域名的apache rewrite规则

不说原因直接开,需求就是搞了个https免费证书,要求所有http请求都跳转到https,并且www域名跳转到不到www的域名,比如请求www.lison.cc跳转到https://lison.cc,而请求lison.cc跳转到https://lison.cc,全站https嘛。

1.首先设置DNS. 我用的cloudflare的CDN,DNS设置看起来是这样的:

cloudflare为lison.cc做的的DNS设置

2.设置openshift你的application的alias。
默认的有lisonliou-osrd.rhcloud.com,然后再添加lison.cc,www.lison.cc,这是域名绑定?不是很清楚,我就是卡在这里好几个钟头。。。

3.设置转发规则。
我用的apache服务器,所以只需要修改.htaccess文件,添加如下行:

 

第一个rewrite规则是将带www(或者其他,因为已经做了泛解析)的网址跳转到https://aixiadianying.com;

第二个rewrite是将http请求定向到https,实现全站https,就是这样。

最后为业余时间做的站露个脸:爱下电影网 – 一个可以下载电影的网站~ !

Happy Holiday~

javascript使用persistjs跨页面存储读取数据

折腾记:

两个html文件html1和html2,要求使用js在html1中保存数据在html2中能够读取出来,不用数据库、不用session、不用xxx。

PersistJs这个js库。

html1文件的内容:

html2文件内容:

剩下的就在控制台查看效果吧。

本文严重符合伸手COPY党口味,之前有见到大神的PersistJs Demo文章,虽然就几句话,但是一直调试不通,自己折腾了十好几分钟才ok,记下。

据说这厮跨浏览器通用,而且若不支持html5,则自动使用cookie存储(我没验证),真是居家旅行、杀人放火必备之精品啊。

PHP框架ACI动态设置页面SEO信息

背景:

PHP框架 CI 不多说,ACI框架同样不多说,说一下如何为ACI框架的每个页面设置单独的SEO信息。直接说源码部分(本文做折腾记录,面向php技能比较生的手,或者出家时不是修行的php,而是半路改行的家伙)。

需求:
1.为每个页面设置固定的SEO信息
2.为单个页面动态设置SEO信息,例如产品详情页,动态展示产品名称,参数(对应title、keyword等内容)

涉及到的文件:
1. application/config/seo.php
2. application/core/MY_Controller.php
3. application/views/template/header.php
4. 自定义的Controller

折腾:
ACI安装完成之后,要为单独页面设置SEO,先来看下源码目录结构,大约找到了这个文件:application/config/seo.php,打开之后将$config[‘seo’][‘default’] 修改成我们自己的title, keyword,description之后果然生效了,OK, 这是第一步。

上面的修改之所以能够生效,原因在于application/views/template/header.php这个文件,打开之后发现head中有如下代码:

很明显$title, $keyword, $description都是动态设置的(废了个话),然后就应该找到每个页面对应的Controller,于是第二步顺藤摸瓜,找到welcome.php的controller页面,发现controller里面没有任何关于设置title、keyword的东西。然后看一下Welcome的继承关系( ->代表继承关系):
Welcome -> Front_Controller-> MY_Controller -> CI_Controller

看一下MY_Controller的代码:

主要看标红的部分,$_default_pageseo是没有设置seo信息时默认的内容,就是第一步seo.php里修改的文字,若设置了seo信息,则从$_pageseo里获取,$_pageseo的内容来自哪里?来自seo.php,新增一个的话:

movie是对应的controller名字,这样实现的是固定的页面seo内容。

我的问题是,动态的SEO内容,就像打开一个产品页面,显示每一个具体产品的SEO信息,而不是一个固定的。

OK,解决方法是在Front_Controller中加入方法:

上面代码不做解释,然后在每个Controller的action中,渲染页面之前($this->view()),调用$this->seo($title, $keyword, $description)。

就是这样,中午没睡好,脑子不灵,语言组织不搭。。。

树莓派学习使用入门资料整理 – Raspberry PI

关于[Python],人生苦短,我用python

Python2.x 与Python3.x 存在严重的兼容性问题

关于opencv

OpenCV 编程简介(矩阵/图像/视频的基本读写操作)
Emgu cv Tutorial

关于Linux学习

关于树莓派

树莓派入门指南
用python让树莓派说话
树莓派吧
树莓派官方社区Python讨论版
极客工仿树莓派板块
树莓派中文站
Mike’s Electric Stuff 查设备sheet
树莓派I2C接口扩展
树莓派GPIO使用
探索Wiring Pi
Wiringpi.com 官网
Café
AllDatasheet
Search Datasheet
Handbook of hardware schemes, cables layouts and connectors pinouts
All Pinouts
AdaFruit
Asterisk搭建VoIP
树莓派学习索引

Android WebView JS 与 Java Native 相互调用示例

直接上代码,有注释,学习Android过程记录。

Android Activity代码

布局文件LinearLayout布局,orentation=vertical,一个EditText,一个Button一个WebView,长什么样子的话想象一下就好了。

html文件,同样非常简单

参考资料:developer.android.com WebView

源码下载:WebViewNJs

Python 文件内容读取示例

整理了一些数据需要批量更新到数据库,内容如:

001      009
002     008
003     007

要生成的语句:update table_name set column=009 where id=001

使用python一共三行语句:

  1. open方法是内置方法(Build-in function),文档解释为:Open file and return a corresponding file object,打开文件并且返回该文件对象。
  2. 将line转换为string并分割成数组,split方法若不加任何参数则默认使用任何空白字符(空格,制表符等)进行分割,并且自动去处数组内的空白元素,太方便了,split官方说明:S.split(sep=None, maxsplit=-1) -> list of strings

    Return a list of the words in S, using sep as the
    delimiter string. If maxsplit is given, at most maxsplit
    splits are done. If sep is not specified or is None, any
    whitespace string is a separator and empty strings are
    removed from the result.

  3. 这行就是组织sql语句了

人生苦短,我用python