最近总结的Android笔记(三)

来源:互联网 发布:360软件管家手机官方 编辑:程序博客网 时间:2024/05/14 21:54

android系统增加framework服务

  1. 在 frameworks/base/core/java/android/os目录中增加对应的aidl文件

  2. 在frameworks/base/Android.mk文件中增加定义的aidl文件
    LOCAL_SRC_FILES +=

  3. mmm frameworks/base
    此时会自动根据aidl文件生成对应的stub接口

  4. 在frameworks/base/services/java/com/android/server目录中,新增对应的service,继承自之前生成的stub接口

  5. 修改frameworks/base/services/java/com/android/server/SystemServer.java文件中注册该服务
    ServiceManager.addService(“hello”, new HelloService());

  6. 在frameworks/base/core/java/android/app/SystemServiceRegistry.java文件中注册该服务
    registerService

  7. 在frameworks/base/core/java/android/content/Context.java中增加Service名称定义

  8. 由于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;列出手机中的所有serviceadb 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/bigfilecontent命令的使用:使用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 systemalarm_alert=content://media/internal/audio/media/18alarm_alert_set=1dim_screen=1dtmf_tone=1dtmf_tone_type=0font_scale=1.0haptic_feedback_enabled=1hearing_aid=0lockscreen_sounds_enabled=0mode_ringer_streams_affected=422mute_streams_affected=46next_alarm_formatted=notification_light_pulse=1notification_sound=content://media/internal/audio/media/88notification_sound_set=1pointer_speed=0ringtone=content://media/internal/audio/media/128ringtone_set=1screen_brightness=149screen_brightness_mode=1screen_off_timeout=600000show_password=1sound_effects_enabled=1status_bar_show_battery_percent=1transition_animation_scale=0.5vibrate_when_ringing=0volume_alarm=6volume_bluetooth_sco=7volume_music=11volume_music_bt_a2dp=8volume_music_bt_a2dp_hp=8volume_music_headphone=8volume_music_headset=8volume_music_usb_accessory=8volume_music_usb_device=8volume_notification=5volume_ring=5volume_system=7volume_voice=4window_animation_scale=1.0设置字体大小为3.0adb shell settings put system font_scale 3.0获取指定应用的oom_adj值大小:ps | grep PackageName //获取你指定的进程信息cat proc/进程号/oom_adjappops get com.android.mms 获取当前应用的权限appops set com.android.mms READ_EXTERNAL_STORAGE allowcom.android.mms from uid 10034 not allowed to perform WRITE_EXTERNAL_STORAGEime 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.txt1080 642 20    1080 642代表屏幕的分辨率,20表示20帧每秒,简单地说20代表一秒钟播放20张图片;p 1 0 文件夹1    p代表标志符play,1代表循环次数为1次,0代表离读取part1的停顿时间为0p 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 apktoolsudo chmod +x apktool.jarapktool 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/xLogLog管理工具https://github.com/binIoter/GuideView最最轻量级的新手引导库,能够快速为任何一个View创建一个遮罩层,支持单个页面,多个引导提示,支持为高亮区域设置不同的图形,支持引导动画https://github.com/JZ-Darkal/AndroidHttpCaptureAndroidHttpCapture网络诊断工具 是一款针对于移动流量劫持而开发的手机抓包软件 主要功能包括:手机端抓包、PING/DNS/TraceRoute诊断、抓包HAR数据上传分享。你也可以看成是Android版的"Fiddler"https://github.com/naman14/AlgorithmVisualizer-Android一个展示各种算法可视化的 Appmaterial控件使用文档http://materialdoc.cnandroid原码解析:https://github.com/LittleFriendsGroup/AndroidSdkSourceAnalysisPixel中文网http://www.pixcn.cn/article-1331-1.html

需要学习的点

android输入系统android 自定义输入法HandlerThread使用和源码分析颜色渐变算法Zen Mode 模式RenderScriptLowMemoryKillerAppOpsManager调用隐藏APIRxJavaRxAndnroidflexboxlayoutkotlinBitMask的使用android阻尼效果GlidebutterknifeRetrofitDagger2bugly干货分享唤醒屏幕呼吸灯实现

进程保活

  • 将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
@Overridepublic 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方法
@Overridepublic 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 -vgit 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 0
原创粉丝点击