本文是基于Android5.1的代码
在做定制需求的时候,需要修改系统通知的声音,将其禁用掉,避免第三方应用发送通知时,声音很大,吓着用户。索性就把通知声音关掉。下面就说说关闭声音的几种方法,以及修改系统默认声音的方法。

1. 直接修改系统层默认的声音大小

在系统代码frameworks/base/media/java/android/media/AudioService.java的开头定义了两个数组,一个MAX_STREAM_VOLUME 这里面定义了各种声音的最大值(最大值不是100,所以需要AudioManager.getStreamMaxVolume(type)来获取各个音量的最大值),然后进行设置。
还定义了一个数组DEFAULT_STREAM_VOLUME 这里面则和MAX_STREAM_VOLUME里定义的顺序是一样,表明了各种声音的默认的大小。此块代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/** @hide Maximum volume index values for audio streams */
private static int[] MAX_STREAM_VOLUME = new int[] {
5, // STREAM_VOICE_CALL
7, // STREAM_SYSTEMX_STREAM_VOLUMEMAX_STREAM_VOLUMEMAX_STREAM_VOLUME
7, // STREAM_RING
15, // STREAM_MUSIC
7, // STREAM_ALARM
7, // STREAM_NOTIFICATION
15, // STREAM_BLUETOOTH_SCO
7, // STREAM_SYSTEM_ENFORCED
15, // STREAM_DTMF
15 // STREAM_TTS
};

private static int[] DEFAULT_STREAM_VOLUME = new int[] {
4, // STREAM_VOICE_CALL
7, // STREAM_SYSTEM
5, // STREAM_RING
11, // STREAM_MUSIC
6, // STREAM_ALARM
5, // STREAM_NOTIFICATION
7, // STREAM_BLUETOOTH_SCO
7, // STREAM_SYSTEM_ENFORCED
11, // STREAM_DTMF
11 // STREAM_TTS
};

如果我们需要修改默认的通知声音,则可以将STREAM_NOTIFICATION 前面的数值 5 给为 0即可,这样默认声音就为0 了。

2. 修改数据库中的通知声音值

媒体声音这些数据在数据库中都会默认的存放数据,我们知道大多数的数据都是系统初次启动的时候在SettingProvider应用中加载初始化的值,当然通知的声音也在里面。

阅读全文 »

问题:

在使用扫码枪扫码条码的时候明明有字母和字符,但是输入到Android系统却没哟,输入到电脑是正常的,这就很奇怪,让一个搞上层开发的摸不着头脑,最后和系统讨论才知道是系统按键部分映射被删除导致的。

解决办法:

  1. 在Android系统层frameworks/base/data/keyboards文件夹下面有Generic.kl这个文件,此文件为Android默认的按键映射对应表,还有其他的比如:qwerty.kl文件,以及一些自定义码值的kl文件。
  2. 打开Generic.kl看看类型也许就明白了.
    1
    key 11      0
    key 2       1
    key 3       2
    key 4       3
    key 5       4
    key 6       5
    key 7       6
    key 8       7
    key 9       8
    key 10      9
    key 12      MINUS
    key 13      EQUALS
    key 14      DEL
    key 15      TAB

里面是键与键值的映射,比如:键值11 对应的按键为 0 这个,以此类推。那解决就明朗了,将所有字母和字符的按键映射添加进行就ok了,至于按键值是多少我这边直接参考了另外一个平台的Generic.kl文件。重新编译系统验证,此问题解决了。

疑惑问题:

  1. 用相同Android版本的android.jar 查看keyCode对应的值和Generic.kl文件里描述的不一样,此问题还没有弄明白为什么,系统说两个是不相关的?
  2. 发现在两个平台上有大部分按键值在一致的,但存在分别的是不样的,不明白怎么定义的。依据是啥?

参考文章

http://blog.csdn.net/kangear/article/details/12110951
http://blog.csdn.net/mjsornp/article/details/39988275
https://www.zhihu.com/question/20830530

首先找到系统对应系统签名keys的位置,一般在源码的android\build\target\product\security,此文件夹下面有4个标准的key。

  • testkey – a generic key for packages that do not otherwise specify a key.
  • platform – a test key for packages that are part of the core platform.
  • shared – a test key for things that are shared in the home/contacts process.
  • media – a test key for packages that are part of the media/download system.

注:我们需要制作的keystore需要用到platform的key。

直接签名和制作keystore都是需要使用platform.x509.pemplatform.pk8这两个文件。

直接给应用签名

直接签名还需要一个signapk.jar文件,此文件位置在out/host/linux-x86/framework/signapk.jar 在利用上面文件签名,命令如下:
java -jar signapk.jar platform.x509.pem platform.pk8 app.apk app_signed.apk

app_signed.apk为经过系统签名的apk了。

制作keystore

使用上面两个文件来生成keysotre。按照如下步骤进行生成:

  1. 生成platform.pem
    openssl pkcs8 -inform DER -nocrypt -in platform.pk8 -out platform.pem
  2. 生成platform.pk12
    openssl pkcs12 -export -in platform.x509.pem -out platform.p12 -inkey platform.pem -password pass:android -name androiddebugkey
  3. 生成keystore文件
    keytool -importkeystore -deststorepass android -destkeystore ./platform.keystore -srckeystore ./platform.p12 -srcstoretype PKCS12 -srcstorepass android

注:有的生成的为platform.jks,可以直接改为.keystore后缀,不影响使用的。

基于以上我们就能够制作出keystore。

参考链接:
http://elsila.blog.163.com/blog/static/173197158201211172281242/
https://developer.android.com/studio/publish/app-signing.html
http://jmlinnik.blogspot.com/2011/12/keystores.html

来自: Android梦想特工队
作者: Aaron
主页: http://www.wxtlife.com/
原文连接: http://www.wxtlife.com/2016/05/12/editext-use-summary/

EditText点击首次获得焦点后默认光标在最后的实现

这个本身是一个比较简单的问题了,大家一想都知道,设置OnFocusChangeListener方法,在hasFocus为true时调用setSelection(int)方法将光标移动到最后的位置。然后将事件绑定到EditText上即可,但是但是… 不起作用,不起作用,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
editText.setOnFocusChangeListener(mFocusChangeListener);

private View.OnFocusChangeListener mFocusChangeListener = new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus) {
Log.v("Aaron","has focus ");
setEditTextCursorToLast();
}
}};

private void setEditTextCursorToLast() {
editText.setSelection(editText.getText().toString().length());
}

百思不得其解,搜索半天各种方法试过一轮后,怀疑是点击时候是先执行了onFocus,之后由于点击事件强制将光标又移至到点击的位置,导致不能设置的问题。那么尝试解决这个问题就是在focus的时候延迟下执行。。。把上面方法改为如下:

1
2
3
4
5
6
7
8
private void setEditTextCursorToLast() {   
edittext.post( new Runnable() {
@Override
public void run() {
mMailTitleEditText.setSelection(mMailTitleEditText.getText().toString().length());
}
});
}

其实也没有怎么延迟了。。仅仅是把执行的代码放在了一个runnable里面,然后结果就是这么神奇,结果起作用了。。

如果谁知道是什么原理请告知,不慎感激。

在java中垃圾回收是系统自动完成的,了解它对优化应用程序有很大的帮助。那么我们就从下面几个方面来了解垃圾回收机制:

  1. 哪些对象需要回收?
  2. 什么时候回收?
  3. 怎么去回收?

判断对象可以回收的方法:

引用计数算法

引用计数

给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。

优点:简单,高效,现在的objective-c用的就是这种算法。
缺点:很难处理循环引用,相互引用的两个对象则无法释放。

可达性分析算法(根搜索算法)

可达性分析
从GC Roots(每种具体实现对GC Roots有不同的定义)作为起点,向下搜索它们引用的对象,可以生成一棵引用树,树的节点视为可达对象,反之视为不可达。
在Java语言中,可以作为GC Roots的对象包括下面几种:

  • 虚拟机栈(栈帧中的本地变量表)中的引用对象。
  • 方法区中的类静态属性引用的对象。
  • 方法区中的常量引用的对象。
  • 本地方法栈中JNI(Native方法)的引用对象

真正标记以为对象为可回收状态至少要标记两次。

常见概念介绍

引用类型分类

引用类型有四种类型分别是:强引用(Strong Reference)、软引用(soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference),其中强引用是我们常用到的。下面来说明下他们什么时候会被垃圾回收机制回收。
强引用: 这种最顽强,只要有一个引用存在,永远都不会被回收掉。
软引用: 一般是指还有用,但是非必须的对象。在内存空间不足的情况下,会回收掉此部分内存,如果还不够则会抛出内存溢出异常。
弱引用: 一般指非必须的对象,比软引用还要弱,它只能生存到下一次垃圾回收前,如果一旦发生垃圾回收,它将会被回收掉。
虚引用: 最弱的引用关系,无法通过虚引用来取得一个对象的实例。为一个对象设置虚引用的唯一目的就是能够在这个对象被回收的时候收到一个系统通知。

阅读全文 »

最近编译服务器出现一个诡异问题,代码被莫名的修改了,于是乎就查找服务器上又有的登录信息,以及操作指令,但最终都没有找到比较有效的信息。但为什么还写这个呢,是因为这里记录下,怎么把服务器上的所有操作记录的信息记录全点呢?以及查看信息用到的一些简单命令。

查看用户登录的情况

常用的有wholast命令

who命令

首先使用who命令可以查看当前服务器上有哪些用户在使用。
语法: who [-Himqsw][–help][–version][am i][记录文件]
参数:
  -H 显示各栏位的标题信息列。
  -i或-u 显示闲置时间,若该用户在前一分钟之内有进行任何动作,将标示成”.”号,如果该用户已超过24小时没有任何动作,则标示出”old”字符串。
  -m  此参数的效果和指定”am i”字符串相同。
  -q或–count 只显示登入系统的帐号名称和总人数
who am i (whoami)这个命令查看当前终端是哪个用户的信息。

last命令

使用last命令可以查看最近的服务器登录情况。
语法: last [-adRx][-f <记录文件>][-n <显示列数>][帐号名称…][终端机编号…]
参数:
  -a  把从何处登入系统的主机名称或IP地址,显示在最后一行。
  -d  将IP地址转换成主机名称。
  -f  <记录文件>  指定记录文件。
  -n  <显示列数>或-<显示列数>  设置列出名单的显示列数。
  -R  不显示登入系统的主机名称或IP地址。
  -x  显示系统关机,重新开机,以及执行等级的改变等信息。
  -i  显示指定ip的登录情况
  -t  显示YYYYMMDDHHMMSS之前的信息
单独执行last指令,它会读取位于/var/log目录下,名称为wtmp的文件,并把该给文件的内容记录的登入系统的用户名单全部显示出来。

默认读取的是wtmp文件,还有一个/var/log/btmp文件,这里面记录了更加全的信息,可以查看。可使用-f 参数指定文件,显示出来。

查看历史操作记录

历史命令的操作我们常用的就是history 这个命令能看所有的操作命令,但是默认的很单调没有很多的详细信息,下面就是修改配置,来增加我们的详细信息。

history命令

默认显示的是一个简单的编号和命令,想要查找一些有用的信息都无法查看到,所以要对其进行修改。

  1. 修改history命令记录的长度和文件大小及显示时间格式
    在系统修改/etc/bash.bashrc文件,在最后面加入下面的语句

    1
    HISTFILESIZE=20000
    HISTSIZE=20000
    HISTTIMEFORMAT="%Y%m%d-%H%M%S:"
    export HISTTIMEFORMAT
  2. 设置history默认的格式
    在系统中修改/etc/profile文件,在文件的最后加入下面语句:

    1
    #设置history格式
    export HISTTIMEFORMAT="[%F %T] [`who am i 2>/dev/null| awk '{print $NF}'|sed -e 's/[()]//g'`] "
    #实时记录用户在shell中执行的每一条命令
    export PROMPT_COMMAND='\
        if [ -z "$OLD_PWD" ];then
            export OLD_PWD=$PWD;
        fi;
        if [ ! -z "$LAST_CMD" ] && [ "$(history 1)" != "$LAST_CMD" ]; then
            logger -t `whoami`_shell_cmd "[$OLD_PWD]$(history 1)";
        fi ;
        export LAST_CMD="$(history 1)";
        export OLD_PWD=$PWD;'

上面这个脚本可以记录下在哪个目录执行了哪些操作以及时间等信息,这样就可以方便我们查看在服务器上谁什么时间在哪个目录执行了哪些操作。

需要退出终端重新进行登录,然后在执行history 就能看到效果了。

其他

  1. time 函数
    time 函数可以统计命令执行的时间,包括程序的实际运行时间(real time),以及程序运行在用户态的时间(user time)和内核态的时间(sys time)。
    例如:time git pull 则是统计更新代码花费多长时间

  2. Linux 简单统计
    在一个文本文件中,每行一个记录,但可能会有重复的,需要统计出来每个重复了多少次并进行合并,且可以输出头几个。则使用tr,uniq, sort 命令则可以进行简单的统计。代码如下:
    echo "ab bc ac ac ab cd" | tr " " "\n" | sort | uniq -c | sort -r | HEAD -n5

Https 介绍

什么是Https

HTTPS(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL

Https的作用

  • 内容加密 建立一个信息安全通道,来保证数据传输的安全;
  • 身份认证 确认网站的真实性
  • 数据完整性 防止内容被第三方冒充或者篡改

Https的劣势

  • 对数据进行加解密决定了它比http慢

    需要进行非对称的加解密,且需要三次握手。首次连接比较慢点,当然现在也有很多的优化。

出于安全考虑,浏览器不会在本地保存HTTPS缓存。实际上,只要在HTTP头中使用特定命令,HTTPS是可以缓存的。Firefox默认只在内存中缓存HTTPS。但是,只要头命令中有Cache-Control: Public,缓存就会被写到硬盘上。 IE只要http头允许就可以缓存https内容,缓存策略与是否使用HTTPS协议无关。

HTTPS和HTTP的区别

  • https协议需要到CA申请证书。
  • http是超文本传输协议,信息是明文传输;https 则是具有安全性的ssl加密传输协议。
  • http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
  • http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

http默认使用80端口,https默认使用443端口

下面就是https的整个架构,现在的https基本都使用TLS了,因为更加安全,所以下图中的SSL应该换为SSL/TLS

Https层次结构

下面就上图中的知识点进行一个大概的介绍。

加解密相关知识

对称加密

对称加密(也叫私钥加密)指加密和解密使用相同密钥的加密算法。有时又叫传统密码算法,就是加密密钥能够从解密密钥中推算出来,同时解密密钥也可以从加密密钥中推算出来。而在大多数的对称算法中,加密密钥和解密密钥是相同的,所以也称这种加密算法为秘密密钥算法或单密钥算法。
常见的对称加密有:DES(Data Encryption Standard)、AES(Advanced Encryption Standard)、RC4、IDEA

阅读全文 »

在数据访问中,内存的访问速度肯定是最快的,所以对于有些文件需要频繁高效访问的时候就可以考虑使用内存映射进行直接读写操作,代替IO读写,达到更高的效率。下面就是要简单说下,怎么来实现简单的Android内存映射。

大致需求

先说下,我这边的需求,多个应用需要读写同一个标记位,且在Android的Input事件系统层也要去读取此标记位,而且频率非常大。所以之前的读写文件法,写系统属性法,对于这种高效率要求的明显已经不能满足了。所以就得考虑直接读取内存值的方法了。

C++层映射

C++已经很久没有接触了,好多都已经还给老师了。(忧伤。。。)所以下面有些不对的地方请指出,谢谢。

基础准备

C++ open函数介绍

打开文件是很常见的一个函数了,但是里面有很多的参数需要注意,所以在这里进行大概的介绍下。
头文件:#include #include #include
函数定义:

1
2
int open(const char * pathname, int flags);
int open(const char * pathname, int flags, mode_t mode);

函数说明

  • 参数 pathname: 指向欲打开的文件路径字符串.
  • 参数flags 所能使用的标志,想读写权限,是否新建等。
  • 参数mode_tmodel 主要文件权限,只有新建文件才有效。

参考地址:http://c.biancheng.net/cpp/html/238.html

C++ mmap函数介绍

在c++中有一个专门的函数是做内存映射的,函数为mmap,它的方法的全称及参数如下:
void *mmap(void *start,size_t length,int prot,int flags,int fd,off_t offsize);
下面是各个参数的意义参考地址mmap参数介绍,我这里搬过来方便查看。

阅读全文 »

在我们都痛恨手机厂商预装着一堆无用的app时,是否考虑怎么实现将app预装在data区,让用户可以自由卸载,做一个有良心的厂商,下面就把来说说如何实现预装app能够让用户卸载。

系统识别的app位置

系统能够识别到app的位置有三个,分别是/system/app/,/system/priv-app /data/app/ 下面。但是只有/data/app下面的app才可以被用户可以卸载。那就得想办法将apk放在/data/app下面。

尝试将预装app放进升级包data区中

根据编译的情况知道,一般在源码下编译的应用都会被放在out/targe/.../system/app或者out/targe/.../system/priv-app下面,用户区是在/data/app/ ,如果在编译后打包前copy某个app到/data/app/下面,且打包的系统img是只会在system区起作用,在data区是不起作用的。所以这种方案不行,只能将app放在system区的文件中了。

在编译时预制到系统system目录中

先将放在系统编译到某个目录下面,我这边放在android/kk-4.x/device/mtk/mtk/preinstall/apk下面,由于现在使用的平台为mtk所以放在mtk下面,preinstall为自己创建的文件夹,以及子目录apk,然后将所有app放在此目录下,当然这样是不能被打包到系统目录的,然后在preinstall目录下面创建一个preinstall.mk文件,当然名字随便了,里面的主要功能就是copy预装的app到系统分区目录中。

阅读全文 »

Activity调用startActivityForResult会立马返回,不能正常调用

在PopupWindow中的EditText不能获取焦点,显示键盘

  • 原因:
    原因为Popupwindow 默认没有获取到焦点,需要手动设置焦点,这样子view才能获取到事件的监听。

  • 解决办法:
    在创建完popwindow后设置他的焦点,popupWindow.setFocusable(true);就可以了。

    阅读全文 »