LOCAL_MODULE_TAGS :=user debug eng tests optional
user: 指该模块只在user版本下才编译
debug: 批该模块只在userdebug版本下才编译
eng: 指该模块只在eng版本下才编译
tests: 指该模块只在tests版本下才编译
optional:指该模块在所有版本下都编译(但只有在PRODUCT_PACKAGES中定义的模块才会被安装?)
LOCAL_MODULE_TAGS :=user debug eng tests optional
user: 指该模块只在user版本下才编译
debug: 批该模块只在userdebug版本下才编译
eng: 指该模块只在eng版本下才编译
tests: 指该模块只在tests版本下才编译
optional:指该模块在所有版本下都编译(但只有在PRODUCT_PACKAGES中定义的模块才会被安装?)
1. gRPC – 远程RPC框架
适用平台:c++、Java、Python、Php、Js等多平台
2. Netty -基于Java NIO client-server的网络应用框架
适用平台:Java
3. thrift – 用于可扩展的跨语言服务开发,简单来说就是RPC远程调用,它是一个完整的 RPC 框架体系。
适用平台:Actionscript 3.0、c_glib、C++、CSharp、D、Dart、Delphi、Go、Graphviz、Haxe Framework、Haskell、Java、Javascript、Node.js、OCaml、Perl、PHP、Python、Ruby
4. SOME/IP(vsomeip) – 用于车载的远程通讯框架,特点:服务发现\带宽预留,符合autosar(汽车开放系统架构)标准.SOME/IP是指协议栈,vsomeip是用c++的实现
适用平台:C/C++
疑问一:如果创建Handler没有为Handler指定Looper,那么Handler用的是哪个Looper?
答:如果没有指定Looper的话,程序会通过Looper.myLooper();来获取当前线程中保存的Looper对象.
扩展:如果一个线程中没有Looper实例,则在创建Handler时即会触发异常
疑问二:如果在程序中建立了多个Handler,都使用同一个Looper(如使用主线程的Looper),那么消息会在每个Handler中都被处理吗?
答:不会,可以看下Handler代码中,enqueueMessage函数里面,将msg.target设置为了Handler本身.而在Looper的loop函数中,是通过msg.target.dispatchMessage(msg);将消息分发出去的,所以不会造成Handler接收消息的错乱.
疑问三:一个线程能不能有多个Looper?
答:不能,Looper的构造函数是私有的,Looper只能通过它的静态方法prepare()函数来创建,这个函数会检查当前线程中是否已有Looper实例,如果已有会报异常,如果没有则创建一个新的.
疑问四:Handler内存泄漏的原理?
Handler内存泄漏是因为,如果创建非静态的内部Handler类,会隐式的持有外部类的实例,所以当Activity销毁时,Handler有未执行的消息时,就会造成内在的泄漏.
并不是有静态内部Handler类就会引起内存泄漏,假如在Activity销毁后,Handler没有继续要执行的工作,也不会造成内存泄漏。
1.adb remount的作用就是重新挂载安卓的系统分区,使系统分区可读写
2.执行该功能其他的方法:
adb shell su #进入安卓命令行
mount -o rw,remount /system #将文件系统remount为读写权限
记得完事后remount回只读: mount -o ro,remount /system
3.另外一种方法
adb shell su #进入安卓命令行
mount -o rw,remount -t ext3 /dev/block/mmcblk1p21 /system
具体请看下面的表格:
| 
					 1 2 3 4 5 6 7  | 
						    public void overridePendingTransition(int enterAnim, int exitAnim) {         try {             ActivityManagerNative.getDefault().overridePendingTransition(                     mToken, getPackageName(), enterAnim, exitAnim);         } catch (RemoteException e) {         }     }  | 
					
♠ frameworks/base/core/java/android/app/ActivityManagerNative.java
| § ActivityManagerNative.getDefault() 很简单,获取gDefault | ||
		
  | 
||
| § gDefault 一个静态变量,是ActivityManagerService 的代理对象 | ||
		
  | 
♠ frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20  | 
						    @Override     public void overridePendingTransition(IBinder token, String packageName,             int enterAnim, int exitAnim) {         synchronized(this) {             ActivityRecord self = ActivityRecord.isInStackLocked(token);             if (self == null) {                 return;             }             final long origId = Binder.clearCallingIdentity();             if (self.state == ActivityState.RESUMED                     || self.state == ActivityState.PAUSING) {                 mWindowManager.overridePendingAppTransition(packageName,                         enterAnim, exitAnim, null);             }             Binder.restoreCallingIdentity(origId);         }     }  | 
					
| ActivityRecord.isInStackLocked(token); 查询当前Activity是否还在Activity栈中? | ||
		
  | 
||
| 如果还在继续执行Binder.clearCallingIdentity();保存此Activity在Binder中的id,稍候就会使用overridePendingAppTransition执行恢复的操作。 | ||
| 如果当前Activity的状态是活动状态或者将要暂停状态,执行WindowManagerService的overridePendingAppTransition | 
♠ frameworks/base/services/java/com/android/server/wm/WindowManagerService.java
| 
					 1 2 3 4 5 6 7 8  | 
						    @Override     public void overridePendingAppTransition(String packageName,             int enterAnim, int exitAnim, IRemoteCallback startedCallback) {         synchronized(mWindowMap) {             mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim,                     startedCallback);         }     }  | 
					
| 调用AppTransition的overridePendingAppTransition方法(将动画的设置信息都放在AppTransition中了) | ||
		
  | 
||
| 然后WindowManagerService在进行Activity切换的时候就会根据AppTransition的动画设置来显示切换动画了。 | 
1. 执行overridePendingTransition时的调用顺序ActivityManageService->WindowManageService
2. 最终设置的是WindowManagerService的overridePendingAppTransition
3. 和Windows编程中显示模式窗口不同,执行startActivity时并没有立即暂停当前Activity,而是通过Handler在下一个MessageQueue的处理中暂停的当前Activity
一、问题
通过adb连接android设备时,出现了如下错误:
error: insufficient permissions for device: user in plugdev group; are your udev rules wrong?
See [http://developer.android.com/tools/device.html] for more information
二、解决办法
首先在插上usb设备和拔下设备时各执行一次lsusb命令,可以看到插上设备比拔掉设备时结果多出一行,如下:
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16  | 
						连接设备时 Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 001 Device 006: ID 0bda:0129 Realtek Semiconductor Corp. RTS5129 Card Reader Controller Bus 001 Device 005: ID 8087:0a2a Intel Corp.  Bus 001 Device 004: ID 1bcf:2b8a Sunplus Innovation Technology Inc.  Bus 001 Device 007: ID 2207:0010  Bus 001 Device 002: ID 25a7:fa23  Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub 拔掉时 Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 001 Device 006: ID 0bda:0129 Realtek Semiconductor Corp. RTS5129 Card Reader Controller Bus 001 Device 005: ID 8087:0a2a Intel Corp.  Bus 001 Device 004: ID 1bcf:2b8a Sunplus Innovation Technology Inc.  Bus 001 Device 002: ID 25a7:fa23  Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub  | 
					
可以看到多了一行
Bus 001 Device 007: ID 2207:0010
然后我们编辑/etc/udev/rules.d/下的51-android.rules文件(如果没有则新建一个此文件),执行命令:
| 
					 1  | 
						sudo gedit /etc/udev/rules.d/51-android.rules  | 
					
然后在文件中增加一行如下内容:
| 
					 1  | 
						SUBSYSTEM=="usb", ATTRS{idVendor}=="2207", ATTRS{idProduct}=="0010",MODE="0666"  | 
					
保存文件后,给51-android.rules加上权限
| 
					 1  | 
						sudo chmod a+x 51-android.rules  | 
					
再重新插上usb线就可以了。
这个精度的损失给本人造成了精神损失! :cry:
整数相除,然后用ceil向上取整,本以为多简单个事,但是搞了半天,整数直接相除得到的结果必定是个整数,即使你把这个结果赋值给一个符点型的变量。
后来才想起来需要强制转换其中一个为符点数然后再相除才可以。看下面的例子:
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15  | 
						#include <iostream> using std::vector; int main(void){ 	int i1 = 3; 	int i2 = 10; 	double d1 = i2 / i1; 	double d2 = (double)i2 / i1; 	std::cout << "d1: " << d1 << "\nd2: " << d2 << std::endl; 	return 0; }  | 
					
输出结果:
| 
					 1 2 3  | 
						bash-3.2$ ./a.out  d1: 3 d2: 3.33333  | 
					
这个例子很简单,我就不解释啦!
关键是有什么办法可以避免这个问题再发生?不能只凭记忆吧?!
需要对Android中的sdcard目录进行扫描,获取文件列表,而且要对文件进行排序
本文使用了非递归的方式进行扫描,用一个栈保存需要扫描的文件夹,用while循环所有目录和文件
排序分为在内部排序和整体排序:
根据最后的测试,外部排序速度明显优于内部排序,内部排序的时间约是外部排序的1.3倍。
基于此优化使用排序,如果场景不允许可以先内部排序满足某些条件后再改为外部排序。
下面为文件扫描类的代码FileScanner.java
| 
					 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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78  | 
						package bcoder.com.androidfunctiontestapplication.utils; import android.util.Log; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.Stack; public class FileScanner {     public static final String LOG_TAG = "FileScanner";     public ArrayList<String> mFileList = new ArrayList<>();     private boolean mIsRunning = true;     public int scanFiles(String path){         mFileList.clear();         File file = new File(path);         Stack<File> folderStack = new Stack<>();         folderStack.push(file);         long starttime = System.currentTimeMillis();         while (!folderStack.empty()){             if(!mIsRunning){                 break;             }             file = folderStack.pop();             File[] files = file.listFiles();             // 内部排序             Arrays.sort(files, new Comparator<File>() {                 @Override                 public int compare(File o1, File o2) {                     return o1.getName().toLowerCase().compareTo(o2.getName().toLowerCase());                 }             });             for(int i = 0; i < files.length;  i++){                 String fullfilepath = files[i].getAbsolutePath();                 if(files[i].isDirectory() && !"./".equals(files[i].getName())){                     folderStack.push(files[i]);                     mFileList.add(fullfilepath);                 } else {                     mFileList.add(fullfilepath);                 }             }         }         long timeuse = System.currentTimeMillis() - starttime;         Log.d(LOG_TAG, String.format("TimeUse: %d", timeuse));         Arrays.sort(mFileList.toArray());         // 外部排序         mFileList.sort(new Comparator<String>() {             @Override             public int compare(String o1, String o2) {                 return o1.compareTo(o2);             }         });         Log.d(LOG_TAG, String.format("File count: %d", mFileList.size())); //        for(int i = 0; i < mFileList.size(); i++){ //            Log.d(LOG_TAG, mFileList.get(i)); //        }         return mFileList.size();     }     public void stopScan(){         mIsRunning = false;     } }  | 
					
github项目地址:https://github.com/wintergoes/AndroidFunctionTestApplication
本文和上一篇文章类似,只是增大了圆角半径的值,所以左右两边看着像椭圆形状,我们先来看看完成后的效果图:
首先,在res/drawable目录下新建一个shape形状,文件名为round_rect_oval_btn_normal.xml,代表按钮正常情况下的样子,代码为:
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15  | 
						<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"        android:shape="rectangle">     <gradient android:startColor="#dcdcdc"               android:endColor="#dcdcdc"               android:centerColor="#f5f5f5"               android:angle="90"               android:centerX="0.4"               android:centerY="0.4"               android:type="linear"></gradient>     <stroke android:color="#aaaaaa"             android:width="1dp"></stroke>     <corners android:radius="50dp"></corners> </shape>  | 
					
第二步,为按钮按下状态新建一个文件,在res/drawable目录下新建文件名为round_rect_oval_btn_pressed.xml,文件内容为;
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15  | 
						<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"        android:shape="rectangle">     <gradient android:startColor="#cccccc"               android:endColor="#cccccc"               android:centerColor="#f5f5f5"               android:angle="90"               android:centerX="0.4"               android:centerY="0.4"               android:type="linear"></gradient>     <stroke android:color="#aaaaaa"             android:width="1dp"></stroke>     <corners android:radius="50dp"></corners> </shape>  | 
					
接下来,把两个样式组合起来,使用selector资源,在res/drawable目录下新建文件round_rect_oval_btn_selector.xml,并输入文件的内容:
| 
					 1 2 3 4 5  | 
						<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android">     <item android:state_pressed="true" android:drawable="@drawable/round_rect_oval_btn_pressed"></item>     <item android:drawable="@drawable/round_rect_oval_btn_normal"></item> </selector>  | 
					
好了,如果你现在想看一下按钮的效果,可以在activity上放一个TextView或者按钮,并设置它的background为@drawable/round_rect_oval_btn_selector。
当然,为了保持代码的简洁和以后方便扩展,我们还是为这类按钮新建一个样式,在res/values/style.xml中新建一个名为round_rect_oval_btn_bkg的样式,并设置如下:
| 
					 1 2 3 4 5  | 
						    <style name="round_rect_oval_btn_bkg">         <item name="android:background">@drawable/round_rect_oval_btn_selector</item>         <item name="android:layout_marginTop">10dp</item>         <item name="android:padding">5dp</item>     </style>  | 
					
现在再回到acitivy中为你的TextView或者按钮设置style属性为style=”@style/round_rect_oval_btn_bkg”就可以了。
在Activity的finish中调用setResult时一定要注意顺序,setResult要在super.finish之前调用,否则返回的结果不正确!如下:
| 
					 1 2 3 4 5 6  | 
						@Override public void finish() {    setResult(RESULT_OK, intent);    super.finish(); }  | 
					
如果不按这个顺序调用,在Activity中的onActivityResult中得到的resultCode是0!Android的坑真TM多啊!