BSD

  • 再发布的产品包含源代码,源代码中必须带有原来代码的BSD协议
  • 如果发布的只是二进制库或者软件,在文档和版权声明中包含原有代码中的BSD协议
  • 不可以用开源代码的作者/机构名字和原来产品的名字做市场推广
    BSD 代码鼓励代码共享,但需要尊重代码作者的著作权。BSD由于允许使用者修改和重新发布代码,也允许使用或在BSD代码上开发商业软件发布和销售,因此是对 商业集成很友好的协议。而很多的公司企业在选用开源产品的时候都首选BSD协议,因为可以完全控制这些第三方的代码,在必要的时候可以修改或者二次开发。

AL2.0

Apache Licence是著名的非盈利开源组织Apache采用的协议。该协议和BSD类似,同样鼓励代码共享和尊重原作者的著作权,同样允许代码修改,再发布(作为开源或商业软件)。需要满足的条件也和BSD类似:

  • 需要给代码的用户一份Apache Licence
  • 如果你修改了代码,需要在被修改的文件中说明。
  • 在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议,商标,专利声明和其他原来作者规定需要包含的说明。
  • 如果再发布的产品中包含一个Notice文件,则在Notice文件中需要带有Apache Licence。你可以在Notice中增加自己的许可,但不可以表现为对Apache Licence构成更改。
    Apache Licence也是对商业应用友好的许可。使用者也可以在需要的时候修改代码来满足需要并作为开源或商业产品发布/销售。

GPL

我们很熟悉的Linux就是采用了GPL。GPL协议和BSD, Apache Licence等鼓励代码重用的许可很不一样。GPL的出发点是代码的开源/免费使用和引用/修改/衍生代码的开源/免费使用,但不允许修改后和衍生的代 码做为闭源的商业软件发布和销售。这也就是为什么我们能用免费的各种linux,包括商业公司的linux和linux上各种各样的由个人,组织,以及商 业软件公司开发的免费软件了。
GPL协议的主要内容是只要在一个软件中使用(”使用”指类库引用,修改后的代码或者衍生代码)GPL 协议的产品,则该软件产品必须也采用GPL协议,既必须也是开源和免费。这就是所谓的”传染性”。GPL协议的产品作为一个单独的产品使用没有任何问题, 还可以享受免费的优势。
由于GPL严格要求使用了GPL类库的软件产品必须使用GPL协议,对于使用GPL协议的开源代码,商业软件或者对代码有保密要求的部门就不适合集成/采用作为类库和二次开发的基础。
其它细节如再发布的时候需要伴随GPL协议等和BSD/Apache等类似。

LGPL

LGPL 是GPL的一个为主要为类库使用设计的开源协议。和GPL要求任何使用/修改/衍生之GPL类库的的软件必须采用GPL协议不同。LGPL 允许商业软件通过类库引用(link)方式使用LGPL类库而不需要开源商业软件的代码。这使得采用LGPL协议的开源代码可以被商业软件作为类库引用并 发布和销售。
但是如果修改LGPL协议的代码或者衍生,则所有修改的代码,涉及修改部分的额外代码和衍生的代码都必须采用LGPL协议。因 此LGPL协议的开源 代码很适合作为第三方类库被商业软件引用,但不适合希望以LGPL协议代码为基础,通过修改和衍生的方式做二次开发的商业软件采用。
GPL/LGPL都保障原作者的知识产权,避免有人利用开源代码复制并开发类似的产品。

MIT

MIT是和BSD一样宽范的许可协议,作者只想保留版权,而无任何其它的限制。也就是说,你必须在你的发行版里包含原许可协议的声明,无论你是以二进制发布的还是以源代码发布的。MIT协议又称麻省理工学院许可证,最初由麻省理工学院开发。
被授权人权利:

  1. 被授权人有权利使用、复制、修改、合并、出版发行、散布、再授权及贩售软件及软件的副本。
  2. 被授权人可根据程式的需要修改授权条款为适当的内容。被授权人义务:在软件和软件的所有副本中都必须包含版权声明和许可声明。

被授权人义务:在软件和软件的所有副本中都必须包含版权声明和许可声明。

RecylerView作为ListView,RecylerView标准化了ViewHolder,不同于ListView中复用convertView是复用的,在RecyclerView把ViewHolder作为缓存的单位。

Read More

使用Shell命令

Android中自带一个input工具,使用方法如下

  1. 模拟按键操作
    1
    2
    3
    adb shell #  进入系统
    input keyevent KEYCODE_BACK # 模拟返回键
    input keyevent keyevent 3 # 模拟返回键

常见的按键可以在http://developer.android.com/reference/android/view/KeyEvent.html查看

  1. 对获得焦点的输入框,输入文本
    1
    input text hello #  输入hello文本

输入的文本不能带空格,也不能是中文

  1. 模拟点击屏幕事件
    1
    input tap 100 200 #  在屏幕坐标(100,200)处点击
注:坐标是从左上角开始计算的

还可以模拟长按、滑动等

  • 命令 input [] […]
    • source 指定输入设备
      • trackball 轨迹球
      • joystick 操控杆
      • touchnavigation
      • mouse
      • keyboard
      • gamepad
      • touchpad
      • dpad
      • stylus
      • touchscreen
    • command 指定动作
      • text (默认设备touchscreen)
      • keyevent [–longpress] … (默认设备keyboard)
      • tap (默认设备touchscreen)
      • swipe [duration(ms)] (默认设备touchscreen)
      • press (默认设备trackball)
      • roll (默认设备trackball)
      • tmode

使用Instrumentation

Instrumentation是Android用来测试的工具,可以监测系统与应用程序之间的交互,可以使用他发送按键或者触屏事件

  • 发送按键

    1
    2
    Instrumentation mInst = new Instrumentation();
    mInst.sendKeyDownUpSync(KeyEvent.KEYCODE_CAMERA); // 同步发送一个按下和弹起事件
  • 触屏事件

    1
    2
    3
    4
    5
    Instrumentation mInst = new Instrumentation();  
    mInst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),
    SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, x, y, 0);
    mInst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),
    SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, x, y, 0);
  • 发送文本

    1
    sendPointerSync("text");

    注:以上代码都需要权限的支持,需要在AndroidManifast.xml中添加 ,但还有一些复杂的问题,可以参考这里

使用内部API

在Android系统中,有些内部的API提供注入事件的方法。因为是内部API,在不同版本上可能变化比较大。使用如果想在普通App中使用,可能需要通过反射机制来调用。

在Android API 16之前,WindownManager有相应的方法提供注入事件的方法,如下:

1
2
3
4
5
6
IBinder wmbinder = ServiceManager.getService("window");  
IWindowManager wm = IWindowManager.Stub.asInterface(wmbinder); //pointer
wm.injectPointerEvent(myMotionEvent, false); //key
wm.injectKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A), false);
wm.injectKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_A), false); //trackball
wm.injectTrackballEvent(myMotionEvent, false);

在API 15之后,引入了InputManager,把上面的哪些injectXXXEvent()方法从WindowManager中移除了。使用方法类似:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
IBinder imBinder = ServiceManager.getService("input");  
IInputManager im = IInputManager.Stub.asInterface(imBinder);

//inject key event
final KeyEvent keyEvent = new KeyEvent(downTime, eventTime, action,
code, repeatCount, metaState, deviceId, scancode,
flags | KeyEvent.FLAG_FROM_SYSTEM |KeyEvent.FLAG_KEEP_TOUCH_MODE | KeyEvent.FLAG_SOFT_KEYBOARD,
source);
event.setSource(InputDevice.SOURCE_ANY)
im.injectInputEvent(keyEvent, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);

//inject pointer event
motionEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
im.injectInputEvent(motionEvent, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);

从API 16开始,InputManager就成了一个公开的类了,可以通过如下方法获得InputManager实例:

1
InputManager im = (InputManager) getSystemService(Context.INPUT_SERVICE);

注意,使用injectEvent()需要申明android:name="android.permission.INJECT_EVENTS"权限。
  1. 使用Nativ/JNI调用
    察看Android设备的/dev/input/目录下的设备:
    1
    2
    3
    4
    5
    6
    7
    shell@user:/dev/input $ ll  
    crw-rw---- root input 13, 64 2013-08-11 18:00 event0
    crw-rw---- root input 13, 65 2013-08-11 18:00 event1
    crw-rw---- root input 13, 66 2013-08-11 18:00 event2
    crw-rw---- root input 13, 67 2013-08-11 18:00 event3
    crw-rw---- root input 13, 68 2013-08-11 18:00 event4
    crw-rw---- root input 13, 69 2013-08-11 18:00 event5

可以看到有一些输入设备节点,同时也提供了一些shell工具来操作这些设备,例如上面第1节中提到的input命令,另外还有getevent和sendevent工具分别来监听和发送事件。这些方法,都可以通过JNI的方式调用。这里需要注意的时间eventX设备都是input的用户组,要直接使用,需要root设备。

特别的是,这里有一个开源项目android-event-injector,使用JNI方法注入事件。当然设备需要root。

  • onAttach() 关联Activity时调用
  • onCreate() 创建Fragment时调用,在这里必须初始化Fragment的基础组件
  • onCreateView() Fragment要绘制自己的界面时调用,这个方法必须返回Fragment的layout,也可以返回null(表示没有界面)
  • onActivityCreated() 当Activity对象完成自己的onCreate方法时调用
  • onStart() Fragment的UI可见时调用
  • onResume() Fragment的UI可交互时调用
  • onPause() Fragment 可见但不可交互时调用
  • onStop() Fragment 完全不可见时调用
  • onDestroyView() Fragment 移除视图时调用
  • onDestroy() 清理View资源时调用
  • onDetach() 失去Activity关联时调用

  • 切换到Fragment(第一次)

    • onAttach
    • onCreate
    • onCreateView
    • onActivityCreated
    • onStart
    • onResume
  • 屏幕熄灭

    • onPause
    • onSaveInstanceState
    • onStop
  • 屏幕解锁

    • onStart
    • onResume
  • 切换到其他Fragment

    • onPause
    • onStop
    • onDestroyView
  • 切换回本身

    • onCreateView
    • onActivityCreated
    • onStart
    • onResume
  • 回到桌面

    • onPause
    • onSaveInstanceState
    • onStop
  • 回到应用

    • onStart
    • onResume
  • 退出应用

    • onPause
    • onStop
    • onDestroyView
    • onDestroy
    • onDetach