March 11, 2016

python基础教程

基础知识

整数和表达式

  1. 长整数,后面加L
  2. 十六进制和八进制,分别为0x与0

变量

  1. 变量的定义,不需要类型。直接赋值。
  2. 变量名只能是字母、数字和下划线。并且不能以数字开头。为什么?

语句与表达式

  1. 表达式有值,而语句没有。

获取用户输入

  1. input与rawinput。input会假设用户输入的是合法的Python表达式。而raw_input只会把所有输入当原始数据。

函数、模块

  1. import导入模块。“模块.函数”
  2. from 模块 import 导入函数。
  3. cmath。复数
  4. __future__

运行脚本

  1. 通过python 脚本文件名
  2. Unix标准。pound bang。 #!. #!/usr/bin/env python放在首行,并且讲改脚本加入可执行权限。

注释

  1. #来注释。

字符串

  1. ""''没啥区别,需要注意配套使用。
  2. 转义\用于字符串转义。
  3. 拼接字符串 +
  4. strrepr的区别。
    • str把值转化为合理形式的字符串----相当于java的toString
    • repr会创建一个字符串,它以合法的python表达式的形式来表示值。---相当于把字符串,转化为代码?
  5. 长字符串:""" """可以用于跨多行,并且'',""不需要进行转义。
  6. 原始字符串:r"",不会把反斜杠当做特殊字符;但是在需要的时候我们还是需要对引号进行转义;而且反斜杠不能放在字符串结尾。
  7. Unicode字符串:u"".python普通字符串在内部是以8位的ASCII码形式存储,Unicode字符串则是存储为16位Unicode字符。注意在3.0里,所有字符串都是Unicode字符串。

关于滑动View

March 11, 2016

Android 滑动View的原理

滚动是View本身的属性

View的窗口和内容的区别。View窗口显示的是view的内容的mScrollX、mScrollY。

View是如何更新视图的

  • draw方法会根据mScrollX、mScrollY去绘制。
  • 在绘制之前,会调用computeScroll方法。

关于scrollTo、scrollBy

  • scrollTo、scrollBy的方法的实质,就是改变mScrollX和mScrollY.

关于computeScroll的作用

  • scrollTo、scrollBy是直接滑动目标位置的,这对用户体验不好。
  • computeScroll就提供了滑动的过程中,再次滑动的机会。

关于Scroller类

  • 作为辅助类,提供更好的交互优化。其实它更像一个Util方法。
  • startScroll方法和fling方法,只是记载开始滑动的时间。
  • 然后在computeScroll里调用scroller的computeScrollOffset方法来计算应该滑动的距离。然后方便开发者调用scrollTo、scrollBy方法, 后刷新view。这样就会再次调用computeScroll实现循环渐进滑动

Zjdroid使用心得

January 17, 2016

ZjDroid使用心得

ZjDroid基础

ZjDroid是由百度安全实验室,出的一款android脱壳工具,号称脱壳神器。他是基于基于Xposed Framewrok的动态逆向分析模块。更多的基础介绍请参照作者文章. 由于某些不可知的原因,最初放在github的开源代码已经被删除。好在网上一些热心好友又在github上放出了当初备份的源码。我自己也整理了一个比较完整的一份(为了应对一些情况,自己做了一些修改)。地址在这里

ZjDroid操作步骤

  1. ZjDroid作为Xposed的模块设置好(注意生成apk的时候依赖的xposed库不要编译进apk)
  2. 运行dump_dexinfo命令。观察日志查看输出结果。
  3. 利用上一步得到的dexpath,运行backsmali命令。最后得到脱壳后的dex文件

ZjDroid原理

ZjDroid是基于Xposed的模块的。ZjDroid通过在应用加载的时候,注册一个BroadcastReceiver,注意这个BroadcastReceiver,是运行在目标dex运行的进程中。然后通过am命令来向这个receiver发送命令的。

每一个apk运行的代码都是在dex里的。而代码运行的时候,这些dex都是需要加载进入内存的。而ZjDroid就是利用hook住dex加载的函数。记住这些dex在内存中的信息的。然后dump_dexinfo也就可以拿到这些dex信息。然后backsmali通过dex在内容中的信息,读取在内容中的dex(通过JNI,也就是提供的so库),然后分析dex文件,最后解析出所有的smali文件的。

ZjDroid使用的时候遇到的坑

  1. 执行backsmali命令一定要adb shell进入手机上,再执行。否则receiver会接受不到命令。
  2. 脱壳某数字公司加壳的时候,根据dumpdexinfo步骤得到的dexpath后,运行的到的backsmali时一直报cookie无效。有可能是加壳做了针对性的修改。考虑到backsmali命令是通过dexPath去找dex在java面的句柄cookie。为何不直接用观察到的cookie直接backsmali。所以我就改动了下代码增加了backsmalicookie命令。最后利用新命令尝试了所有观察到的cookie后,终于成功。
  3. 关于原作者说到的脱壳自家产品的,需要将apk改为jar的方案。我也按照他们的方案尝试了。最后还是目标程序无法运行。有可能百度对这种方案又做了修正。不过,我自己尝试出了一个新的方案。照常ZjDroid apk作为模块配置好后重启,这个时候,目标程序监测到后无法运行。我们把ZjDroid卸掉后,再重装,注意不要重启。这个时候目标程序就可以正常hook并脱壳了。猜测是百度加壳会监测xposed的模块。发现模块卸载后就可以启动了。其实Xposed模块在手机重启后,模块已经加载到内存中,并没有因为卸载而清除。这个时候其实ZjDroid就可以用了。重装上ZjDroid其实是为了提供运行backsmali需要的so库。

ZjDroid存在的问题

  1. backsmali貌似并不能把所有的代码都dump出来。原因我还没研究清楚。有可能是使用的了动态解密关键代码的功能。如果想进一步完整破解。可以参照现有的一份方案Android应用程序通用自动脱壳方法研究从Android运行时出发,打造我们的脱壳神器

android touch event理解

December 30, 2015

理解TouchEvent事件

默认情况下:路径如下:此时LinearLayout:onInterceptTouchEvent返回为false, 先走TextView的onTouchEvent再走ViewGroup的

当TextView的onTouchEvent为false的时候,如下:
I LinearLayout::dispatchTouchEvent::action=ACTION_DOWN
I LinearLayout::onInterceptTouchEvent::action=ACTION_DOWN
I EventTextView::dispatchTouchEvent::action=ACTION_DOWN
I EventTextView::onTouchEvent::action=ACTION_DOWN
I LinearLayout::onTouchEvent::action=ACTION_DOWN
I Activity:onTouchEvent::action=ACTION_DOWN
I Activity:onTouchEvent::action=ACTION_MOVE
I Activity:onTouchEvent::action=ACTION_MOVE
I Activity:onTouchEvent::action=ACTION_MOVE
I Activity:onTouchEvent::action=ACTION_MOVE
I Activity:onTouchEvent::action=ACTION_MOVE
System.out I Activity:onTouchEvent::action=ACTION_MOVE
I Activity:onTouchEvent::action=ACTION_UP
当TextView的onTouchEvent为true的时候,如下:
I/System.out(16085): LinearLayout::dispatchTouchEvent::action=ACTION_DOWN
I/System.out(16085): LinearLayout::onInterceptTouchEvent::action=ACTION_DOWN
I/System.out(16085): EventTextView::dispatchTouchEvent::action=ACTION_DOWN
I/System.out(16085): EventTextView::onTouchEvent::action=ACTION_DOWN
I/System.out(16085): LinearLayout::dispatchTouchEvent::action=ACTION_MOVE
I/System.out(16085): LinearLayout::onInterceptTouchEvent::action=ACTION_MOVE
I/System.out(16085): EventTextView::dispatchTouchEvent::action=ACTION_MOVE
I/System.out(16085): EventTextView::onTouchEvent::action=ACTION_MOVE
I/System.out(16085): LinearLayout::dispatchTouchEvent::action=ACTION_MOVE
I/System.out(16085): LinearLayout::onInterceptTouchEvent::action=ACTION_MOVE
I/System.out(16085): EventTextView::dispatchTouchEvent::action=ACTION_MOVE
I/System.out(16085): EventTextView::onTouchEvent::action=ACTION_MOVE
I/System.out(16085): LinearLayout::dispatchTouchEvent::action=ACTION_MOVE
I/System.out(16085): LinearLayout::onInterceptTouchEvent::action=ACTION_MOVE
I/System.out(16085): EventTextView::dispatchTouchEvent::action=ACTION_MOVE
I/System.out(16085): EventTextView::onTouchEvent::action=ACTION_MOVE
I/System.out(16085): LinearLayout::dispatchTouchEvent::action=ACTION_MOVE
I/System.out(16085): LinearLayout::onInterceptTouchEvent::action=ACTION_MOVE
I/System.out(16085): EventTextView::dispatchTouchEvent::action=ACTION_MOVE
I/System.out(16085): EventTextView::onTouchEvent::action=ACTION_MOVE
I/System.out(16085): LinearLayout::dispatchTouchEvent::action=ACTION_UP
I/System.out(16085): LinearLayout::onInterceptTouchEvent::action=ACTION_UP
I/System.out(16085): EventTextView::dispatchTouchEvent::action=ACTION_UP
I/System.out(16085): EventTextView::onTouchEvent::action=ACTION_UP

当此时LinearLayout:onInterceptTouchEvent返回为true, 就没子view什么事情了。直接走ViewGroup的onTouchEvent

ViewGroup的onTouchEvent为false的时候,如下
I/System.out(13814): LinearLayout::dispatchTouchEvent::action=ACTION_DOWN
I/System.out(13814): LinearLayout::onInterceptTouchEvent::action=ACTION_DOWN
I/System.out(13814): LinearLayout::onTouchEvent::action=ACTION_DOWN
I/System.out(13814): Activity:onTouchEvent::action=ACTION_DOWN
I/System.out(13814): Activity:onTouchEvent::action=Unknow:id=261
I/System.out(13814): Activity:onTouchEvent::action=Unknow:id=517
I/System.out(13814): Activity:onTouchEvent::action=Unknow:id=6
I/System.out(13814): Activity:onTouchEvent::action=ACTION_MOVE
I/System.out(13814): Activity:onTouchEvent::action=Unknow:id=262
I/System.out(13814): Activity:onTouchEvent::action=ACTION_MOVE
I/System.out(13814): Activity:onTouchEvent::action=ACTION_MOVE
I/System.out(13814): Activity:onTouchEvent::action=ACTION_MOVE
I/System.out(13814): Activity:onTouchEvent::action=ACTION_MOVE
I/System.out(13814): Activity:onTouchEvent::action=ACTION_UP
ViewGroup的onTouchEvent为true的时候,如下直接走ViewGroup的onTouchEvent,甚至连ViewGroup本身的onInterceptTouchEvent也不走了。
I/System.out(21195): LinearLayout::dispatchTouchEvent::action=ACTION_DOWN
I/System.out(21195): LinearLayout::onInterceptTouchEvent::action=ACTION_DOWN
I/System.out(21195): LinearLayout::onTouchEvent::action=ACTION_DOWN
I/System.out(21195): LinearLayout::dispatchTouchEvent::action=Unknow:id=261
I/System.out(21195): LinearLayout::onTouchEvent::action=Unknow:id=261
I/System.out(21195): LinearLayout::dispatchTouchEvent::action=Unknow:id=517
I/System.out(21195): LinearLayout::onTouchEvent::action=Unknow:id=517
I/System.out(21195): LinearLayout::dispatchTouchEvent::action=ACTION_MOVE
I/System.out(21195): LinearLayout::onTouchEvent::action=ACTION_MOVE
I/System.out(21195): LinearLayout::dispatchTouchEvent::action=ACTION_MOVE
I/System.out(21195): LinearLayout::onTouchEvent::action=ACTION_MOVE
I/System.out(21195): LinearLayout::dispatchTouchEvent::action=Unknow:id=6
I/System.out(21195): LinearLayout::onTouchEvent::action=Unknow:id=6
I/System.out(21195): LinearLayout::dispatchTouchEvent::action=Unknow:id=6
I/System.out(21195): LinearLayout::onTouchEvent::action=Unknow:id=6
I/System.out(21195): LinearLayout::dispatchTouchEvent::action=ACTION_MOVE
I/System.out(21195): LinearLayout::onTouchEvent::action=ACTION_MOVE
I/System.out(21195): LinearLayout::dispatchTouchEvent::action=ACTION_MOVE
I/System.out(21195): LinearLayout::onTouchEvent::action=ACTION_MOVE
I/System.out(21195): LinearLayout::dispatchTouchEvent::action=ACTION_MOVE
I/System.out(21195): LinearLayout::onTouchEvent::action=ACTION_MOVE
I/System.out(21195): LinearLayout::dispatchTouchEvent::action=ACTION_UP
I/System.out(21195): LinearLayout::onTouchEvent::action=ACTION_UP

总结

其实就我个人理解而言。这套系统的目标其实是这样的。一个touch事件该由谁来消费的问题。touch事件而且只能由onTouchEvent来表示有没有消费。

默认dispatchTouchEvent的情况下:

  • 首先,touch事件,一层一层,从最外层,往里层传递。
  • 到了每一层,每一层的父view都有机会通过onInterceptTouchEvent 返回true,来表示他不希望他的子view接触到事件;通过 onTouchEvent 返回true来表示他消费了事件(注意父view,可以截获事件,可以不消费事件,也就是防止子view接触到事件)
  • 只有有一个view表示他想在ACTION_DOWN的时候,通过onInterceptTouchEvent 来返回true来表示他感兴趣的话。以后到了这一层,直接走其onTouchEvent,连onInterceptTouchEvent 也不会走。
  • 并且,只要一个view,即使onInterceptTouchEvent为false,只要onTouchEvent返回为true。其实也是表示感兴趣。以后直接走其onTouchEvent,连onInterceptTouchEvent 也不会走。
  • 如果一个子view的消费Touch事件(即onTouchEvent返回true),那他的父view的onTouchEvent就无法获取该事件了。

从而达到整个view树中,只有一个view消费了onTouchEvent事件(除了两个view同一层,互相覆盖)。

这么一个效果,都是通过dispatchTouchEvent这个方法来做到的。那么这个效果,要怎么代码实现呢?具体其实就是看ViewGroup的dispatchTouchEvent的方法。

另外还有一个问题。就是其实viewGroup的dispatchTouchEvent起到的作用,我们已经知道了。那么其实view本身就有个dispatchTouchEvent。他是起到什么作用呢?点击啊,双击啊,都是通过onTouchEvent来处理的啊。

ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;
}

if (!result && onTouchEvent(event)) {
result = true;
}

已经清楚的说明到,他会先走setOnTouchEventListener,最后才走onTouchEvent事件的。也很显然的猜测到viewgroup onInterceptTouchEvent为true的时候,后面肯定是要调用到viewgroup的touchEvent的,通过什么方法呢?必然是view的dispatchTouchEvent。

可以自己好好考虑下,要是你,你会怎么实现ViewGroup的dispatchTouchEvent的方法。

java同步

July 06, 2015

理解同步的概念,要区分互斥锁和条件变量。虽然,他们往往在一起使用。

问题

建立三个线程,A线程打印10次A,B线程打印10次B,C线程打印10次C,要求线程同时运行,交替打印10次ABC。这个问题用Object的wait(),notify()就可以很方便的解决。 见http://blog.csdn.net/zyplus/article/details/6672775

注意要点

  • 三个线程的启动顺序不确定
  • 条件判断的时候,注意使用while,而不是if,因为wait会有其他的情况被唤醒

其实上文提供的答案,是存在我所说的三个问题的。 下面是我写的代码:

我的代码

package com.landry;

public class ThreadTest {
    private static Object object = new Object();
    private static Boolean printA = true;
    private static Boolean printB = false;
    private static Boolean printC = false;
    private static int count = 0;
    private static final int MAX = 10;
    public static void main(String... args) {
        new ThreadB().start();
        new ThreadA().start();
        new ThreadC().start();
    }
    public static class ThreadA extends Thread {

        @Override
        public void run() {
            System.out.println("Run A");
            synchronized (object) {
                while (count < 10) {
                    while (!printA) {
                        try {
                            object.notifyAll();
                            object.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println('A');
                    printA = false;
                    printB = true;
                    printC = false;
                }
            }
        }
    }
    public static class ThreadB extends Thread {

        @Override
        public void run() {
            System.out.println("Run B");
            synchronized (object) {
                while (count < 10) {
                    while (!printB) {
                        try {
                            object.notifyAll();
                            object.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println('B');
                    printA = false;
                    printB = false;
                    printC = true;
                }
            }
        }
    }
    public static class ThreadC extends Thread {

        @Override
        public void run() {
            System.out.println("Run C");
            synchronized (object) {
                while (count < 10) {
                    while (!printC) {
                        try {
                            object.notifyAll();
                            object.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println('C');
                    printA = true;
                    printB = false;
                    printC = false;
                    count = count + 1;
                }
            }
        }
    }
}

存在的问题

会多打印一个A出来。

注意理解的地方

  • notifyAll只是唤醒线程,wait操作,才会释放自己的锁。