android系统增加framework服务
在 frameworks/base/core/java/android/os目录中增加对应的aidl文件
在frameworks/base/Android.mk文件中增加定义的aidl文件
LOCAL_SRC_FILES +=mmm frameworks/base
此时会自动根据aidl文件生成对应的stub接口在frameworks/base/services/java/com/android/server目录中,新增对应的service,继承自之前生成的stub接口
修改frameworks/base/services/java/com/android/server/SystemServer.java文件中注册该服务
ServiceManager.addService(“hello”, new HelloService());在frameworks/base/core/java/android/app/SystemServiceRegistry.java文件中注册该服务
registerService在frameworks/base/core/java/android/content/Context.java中增加Service名称定义
由于Android5.1.1中有SeAndroid系统,这个系统中维护了一个系统服务的白名单,如果你要添加的系统服务不在这个白名单中,那么添加系统服务将会失败,这个白名单的路径是:external/sepolicy/service_contexts。
下面是我在这个白名单中添加的一行:
bwservice u:object_r:system_server_service:s0
bwservice就是ServiceManager.addService时输入的服务名。
最好先执行一下make update-api,然后单独编译framework
adb shell实用命令
关于adb shell /system/bin/sh下执行的命令,其源代码都是在frameworks/base/cmds/content/src/com/android/commands目录下
adb shell service list;
列出手机中的所有service
adb shell dumpsys meminfo com.tencent.mm
查看应用的内存使用
adb shell dumpsys statusbar
查看状态栏相关信息
adb shell input keyevent 4
按back键,具体定义在KeyEvent.java中
通过adb设置电池电量,开发中可能会用到
adb shell dumpsys battery set level 80
获取整个设备的电量消耗信息: adb shell dumpsys batterystats | more
获取某个apk的电量消耗信息: adb shell dumpsys batterystats com.Package.name | more
在mnt/sdcard目录下创建一个文件,并且快速增长,填充满手机内部存储空间
adb shell dd if=/dev/zero of=/mnt/sdcard/bigfile
content命令的使用:
使用content命令可以方便我们对系统或者是自定义的ContentProvider中的值进行"增,删,查,改"操作,但前提是必须知道对应的要操作的URI
隐藏系统的statusbar电量显示百分比
adb shell content insert --uri content://settings/system --bind name:s:status_bar_show_battery_percent --bind value:i:0
显示系统的statusbar电量显示百分比
adb shell content insert --uri content://settings/system --bind name:s:status_bar_show_battery_percent --bind value:i:1
使用Settings命令查询和更改SettingsProvider数据库的值
这里使用Settings命令查询和更改数据库的值,就等于我们在代码中使用Settings.System.putInt(getContentResolver(), SCREEN_OFF_TIMEOUT, value)这样的效果
先看下Settings命令的使用介绍:
usage: settings [--user <USER_ID> | current] get namespace key
settings [--user <USER_ID> | current] put namespace key value
settings [--user <USER_ID> | current] delete namespace key
settings [--user <USER_ID> | current] list namespace
列出当前系统中的可以设置的属性
adb shell settings list system
alarm_alert=content://media/internal/audio/media/18
alarm_alert_set=1
dim_screen=1
dtmf_tone=1
dtmf_tone_type=0
font_scale=1.0
haptic_feedback_enabled=1
hearing_aid=0
lockscreen_sounds_enabled=0
mode_ringer_streams_affected=422
mute_streams_affected=46
next_alarm_formatted=
notification_light_pulse=1
notification_sound=content://media/internal/audio/media/88
notification_sound_set=1
pointer_speed=0
ringtone=content://media/internal/audio/media/128
ringtone_set=1
screen_brightness=149
screen_brightness_mode=1
screen_off_timeout=600000
show_password=1
sound_effects_enabled=1
status_bar_show_battery_percent=1
transition_animation_scale=0.5
vibrate_when_ringing=0
volume_alarm=6
volume_bluetooth_sco=7
volume_music=11
volume_music_bt_a2dp=8
volume_music_bt_a2dp_hp=8
volume_music_headphone=8
volume_music_headset=8
volume_music_usb_accessory=8
volume_music_usb_device=8
volume_notification=5
volume_ring=5
volume_system=7
volume_voice=4
window_animation_scale=1.0
设置字体大小为3.0
adb shell settings put system font_scale 3.0
获取指定应用的oom_adj值大小:
ps | grep PackageName //获取你指定的进程信息
cat proc/进程号/oom_adj
appops get com.android.mms 获取当前应用的权限
appops set com.android.mms READ_EXTERNAL_STORAGE allow
com.android.mms from uid 10034 not allowed to perform WRITE_EXTERNAL_STORAGE
ime list -a -s 列出当前设备的所有可输入的包
media dispatch play 播放系统音乐
media dispatch pause
模拟用户事件
- 文本输入
adb shell input text <string> 例手机端输出demo字符串,相应指令:adb shell input "demo".
- 键盘事件
input keyevent <KEYCODE>,其中KEYCODE见本文结尾的附表 例点击返回键,相应指令: input keyevent 4.
- 点击事件
input tap <x> <y> 例点击坐标(500,500
相应指令: input tap 500 500.
- 滑动事件
input swipe <x1> <y1> <x2> <y2> <time>
例从坐标(300,500)滑动到(100,500),
相应指令: input swipe 300 500 100 500. 例200ms时间从坐标(300,500)滑动到(100,500)
相应指令: input swipe 300 500 100 500 200.
开机动画
一般开机动画对应手机中是放在/system/media/bootanimation.zip中的,其中包含对应的配置文件
desc.txt
1080 642 20 1080 642代表屏幕的分辨率,20表示20帧每秒,简单地说20代表一秒钟播放20张图片;
p 1 0 文件夹1 p代表标志符play,1代表循环次数为1次,0代表离读取part1的停顿时间为0
p 0 0 文件夹2 第一个0这里是代表循环播放,第二个0和上面第二条指令一样
c 1 40 文件夹3
第一条指令:[屏幕的分辨率] [播放频率]
第二条指令:[p] [播放次数] [间隔帧数] [文件夹]
第N条指令: 同上
android studio源码导入
// 在android源码目录下执行如下命令,之后导入即可
mmm development/tools/idegen/
development/tools/idegen/idegen.sh
APP反编译
apktool.jar下载
https://bitbucket.org/iBotPeaches/apktool/downloads
将apktool和apktool.jar放置到usr/local/bin目录下,并且设置其为可执行文件
sudo chmod +x apktool
sudo chmod +x apktool.jar
apktool d xxx.apk
反编译的时候可能会出现这样的错误:
com.googlecode.dex2jar.DexException
这是因为当前是odex文件,需要执行下面的操作:
java -jar baksmali-2.0.3.jar -d system/framework -x xxx.odex
-d 参数就是指定到那个目录下寻找那些所需的jar文件,如果所需的jar包就在当前目录,那么就不需要指定该目录了。
命令执行完成之后就会在当前目录下生成一个out目录,该目录里面就是对应的smali文件
这里out目录下存放的是smail文件,我们也可是通过apktool反编译出资源,然后将out替换成我们自己的smaily目录
java -jar smali-2.0.3.jar -o classes.dex out
有趣的工具和网站
https://github.com/skyhacker2/SQLiteOnWeb-Android
一个可以让你在浏览器里管理应用 SQLite 数据库的库
https://github.com/elvishew/xLog
Log管理工具
https://github.com/binIoter/GuideView
最最轻量级的新手引导库,能够快速为任何一个View创建一个遮罩层,支持单个页面,多个引导提示,支持为高亮区域设置不同的图形,支持引导动画
https://github.com/JZ-Darkal/AndroidHttpCapture
AndroidHttpCapture网络诊断工具 是一款针对于移动流量劫持而开发的手机抓包软件 主要功能包括:手机端抓包、PING/DNS/TraceRoute诊断、抓包HAR数据上传分享。你也可以看成是Android版的"Fiddler"
https://github.com/naman14/AlgorithmVisualizer-Android
一个展示各种算法可视化的 App
material控件使用文档
http://materialdoc.cn
android原码解析:
https://github.com/LittleFriendsGroup/AndroidSdkSourceAnalysis
Pixel中文网
http://www.pixcn.cn/article-1331-1.html
需要学习的点
android输入系统
android 自定义输入法
HandlerThread使用和源码分析
颜色渐变算法
Zen Mode 模式
RenderScript
LowMemoryKiller
AppOpsManager
调用隐藏API
RxJava
RxAndnroid
flexboxlayout
kotlin
BitMask的使用
android阻尼效果
Glide
butterknife
Retrofit
Dagger2
bugly干货分享
唤醒屏幕
呼吸灯实现
进程保活
- 将Service设置为前台服务
Notificationnotification = newNotification(R.drawable.notify, "A new message"
, System.currentTimeMillis());
notification.setLatestEventInfo(this, "testtest",
"testtest", null);
//设置通知默认效果
notification.flags = Notification.FLAG_SHOW_LIGHTS;
startForeground(1, notification);
- 在service的onstart方法里返回 STATR_STICK
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
- 添加Manifest文件属性值为android:persistent=“true”
<application android:name="PhoneApp"
android:persistent="true"
android:label="@string/dialerIconLabel"
android:icon="@drawable/ic_launcher_phone">
// 注意:该方法需要系统签名
- 覆写Service的onDestroy方法
@Override
public void onDestroy() {
Intent intent = new Intent(this, KeeLiveService.class);
startService(intent);
super.onDestroy();
}
- 监听系统广播
- 监听第三方应用的静态广播
- 账户同步,定时唤醒
- 应用间互相拉起
- Native进程拉起
- 双进程守护
- 使用AlarmManager唤醒
public void startKeepLiveService(Context context, int timeMillis,String action) {
//获取AlarmManager系统服务
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
//包装Intent
Intent intent = newIntent(context,LiveServie.class);
intent.setAction(action);
PendingIntent pendingIntent = PendingIntent.getService(context,0,intent, PendingIntent.FLAG_UPDATE_CURRENT);
//添加到AlarmManager
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(),timeMillis,pendingIntent);
}
- 一像素悬浮层
首先定义 Activity,并设置 Activity 的大小为1像素:
public class AliveActivity extends AppCompatActivity {
private static final StringTAG="keeplive";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
Window window = getWindow();
window.setGravity(Gravity.LEFT|Gravity.TOP);
WindowManager.LayoutParams params = window.getAttributes();
params.x=0;
params.y=0;
params.height=1;
params.width=1;
window.setAttributes(params);
}
}
其次,从 AndroidManifest 中通过如下属性,排除 Activity 在 RecentTask 中的显示:
<activity
android:name=".AliveActivity"
android:excludeFromRecents="true"
android:exported="false"
android:finishOnTaskLaunch="false"
android:launchMode="singleInstance"
android:process=":live"
android:theme="@style/LiveStyle"
>
</activity>
最后,控制 Activity 为透明:
<stylename="LiveStyle">
<itemname="android:windowBackground">@android:color/transparent</item>
<itemname="android:windowFrame">@null</item>
<itemname="android:windowNoTitle">true</item>
<itemname="android:windowIsFloating">true</item>
<itemname="android:windowIsTranslucent">true</item>
<itemname="android:windowContentOverlay">@null</item>
<itemname="android:windowAnimationStyle">@null</item>
<itemname="android:windowDisablePreview">true</item>
<itemname="android:windowNoDisplay">true</item>
</style>
Activity 启动与销毁时机的控制
public class KeepLiveReceiver extendsBroadcastReceiver {
private ContextmContext;
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
// 这里可以start AliveActivity
} else if (action.equals(Intent.ACTION_USER_PRESENT)) {
// finish AliveActivity
}
}
}
- 灰色代码保活
public class GrayService extends Service {
private final static int GRAY_SERVICE_ID = 1001;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (Build.VERSION.SDK_INT < 18) {
//API < 18 ,此方法能有效隐藏Notification上的图标
startForeground(GRAY_SERVICE_ID, new Notification());
} else {
Intent innerIntent = new Intent(this, GrayInnerService.class);
startService(innerIntent);
startForeground(GRAY_SERVICE_ID, new Notification());
}
return super.onStartCommand(intent, flags, startId);
}
/**
* 给 API >= 18 的平台上用的灰色保活手段
*/
public static class GrayInnerService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startForeground(GRAY_SERVICE_ID, new Notification());
stopForeground(true);
stopSelf();
return super.onStartCommand(intent, flags, startId);
}
}
}
提交代码
git remote -v
git push ... HEAD:refs/for/远程分支名称
ViewGroup相关
ViewGroup默认情况下,出于性能考虑,会被设置成WILL_NOT_DROW,这样,ondraw就不会被执行了,如果我们想重写一个viewgroup的ondraw方法,就要调用setWillNotDraw(false)。
onSizeChanged()方法的启动是在onDraw之前
onFinishInflate():当View中所有的子控件均被映射成xml后触发
onMeasure(int widthMeasureSpec, int heightMeasureSpec):确定所有子元素的大小
onLayout(boolean changed, int l, int t, int r, int b):当View分配所有的子元素的大小和位置时触发
onSizeChanged(int w, int h, int oldw, int oldh):当view的大小发生变化时触发
onDraw(Canvas canvas):负责将View绘制在屏幕上
除非明确使用handle发消息,尽量不要在View中使用Handler,因为view内部本身已经提供了post系列的方法,完全可以替代Handler的作用
view中如果有线程,广播或者动画,需要在onDetachedFromWindow方法中及时停止
对浮点数比较大小时不要使用==
本来应该相等的两个浮点数由于计算机内部表示的原因可能略有微小的误差,这时用==就会认为它们不等。应该使用两个浮点数之间的差异的绝对值小于某个可以接受的值来判断判断它们是否相等,比如用
if (fabs(fOldWidth-fNewWidth) < 0.000001)
来代替
按位与&
两位全为1,结果才为1
按位或||
只要有一个为1,结果就为1
异或运算^
两个相应位,值不同,则结果为1,否则为0
用异或运算实现两个数交换
A = A ^ B
B = A ^ B
A = A ^ B
去反运算~
对一个二进制数,各个位数值取反,即将1变为0,将0变为1
左移运算<<
将一个运算对象的,各个二进制位全部向左移N位,(左边的二进制位丢弃,右边补0)
# 举例
若左移时候,最高位不包含1,那么该数每左移动一位,相当于乘以2
右移运算>>
将一个运算对象的,各个二进制位全部向右移N位,正数左边补0,负数左边补1,右边丢弃,操作数每右移动一位,相当于除以2
无符号右移运算>>>
各个位向右移动指定的位数,右移后,左边空出的位置,用0来补齐,移除右边的位丢弃
源码和反码,补码
一个整数,按照绝对值大小,转换成的二进制数,成为源码
# 14的源码
00000000 00000000 00000000 00001110
将二进制数,按位取返得到的结果
# 14的返码
11111111 11111111 11111111 11110001
将反码加1,得到的数就是补码
# 14的补码
11111111 11111111 11111111 11110010
好了,没有太多的技术点,主要是最近的总结吧,明天不上班,^_^.