过去的开发总是踩到n多的坑,虽然找到了处理的方案并解决,但后继在遇到的时候,大概只记得有这回事,怎么处理又忘记了,所以打算将自己踩过的坑和处理的问题记录下来。
那些坑们:
1、获取的蓝牙的信息没有放在一个统一的单例对象中 T T
设计开发底层库时,涉及到多个应用同时使用同个服务,数据应该要做好分类,那些是不同应用要各自初始化的,那些需要或可以统一使用的。
-----------------------------------------------------------------------------------
好文:开发第三方库最佳实践
-----------------------------------------------------------------------------------
2、在6.0系统下,无法进行自动的匹配甚至接不到任何的广播
原因:加了一个权限:http://www.jianshu.com/p/376b05ed8f4d
自动匹配参考:http://blog.csdn.net/qq_25827845/article/details/52400782
3、由于把不同的功能模块分成了多个module,所以在最后合并生成的时候发现不会把依赖打包进去:
http://zkread.com/article/1150352.html
4、aidl回调传输数据:传的对象中不能包含对象(也许是处理的不对);
5、蓝牙BLE:
a.使用ble的扫描方式时,扫描不到蓝牙2.0设备,硬件的哥们解释是说从机(被连接设备)是单模的,只能被蓝牙2.0扫描模式扫到,但也有资料说ble只能是扫描4.0或2.0,不能同时扫描4.0和2.0设备([转载]蓝牙4.0——Android BLE开发官方文档翻译)
b.由于2.0和4.0的协议改变,所以连接时需要根据不同版本区分处理,device对象的gettype()可以返回设备支持的连接方式
c.ble的写入操作必须在事件完成后再继续。所以需要在onCharacteristicWrite里加上一些处理(阻塞进程是没有用的,还是会有失败的情况)
-----------------------------------------------------------------------------------
6、判断应用是否在后台运行的问题:
红米Note:包名匹配+importance属性比较
其他(华为荣耀,htc):包名匹配即可
7、音/视频声道设置:
音频(AudioTrack):
/** * Sets the specified left and right output gain values on the AudioTrack. * <p>Gain values are clamped to the closed interval [0.0, max] where * max is the value of {@link #getMaxVolume}. * A value of 0.0 results in zero gain (silence), and * a value of 1.0 means unity gain (signal unchanged). * The default value is 1.0 meaning unity gain. * <p>The word "volume" in the API name is historical; this is actually a linear gain. * @param leftGain output gain for the left channel. * @param rightGain output gain for the right channel * @return error code or success, see {@link #SUCCESS}, * {@link #ERROR_INVALID_OPERATION} * @deprecated Applications should use {@link #setVolume} instead, as it * more gracefully scales down to mono, and up to multi-channel content beyond stereo. */ @Deprecated public int setStereoVolume(float leftGain, float rightGain) { if (mState == STATE_UNINITIALIZED) { return ERROR_INVALID_OPERATION; } baseSetVolume(leftGain, rightGain); return SUCCESS; }
视频(MediaPlayer):
/** * Sets the volume on this player. * This API is recommended for balancing the output of audio streams * within an application. Unless you are writing an application to * control user settings, this API should be used in preference to * {@link AudioManager#setStreamVolume(int, int, int)} which sets the volume of ALL streams of * a particular type. Note that the passed volume values are raw scalars in range 0.0 to 1.0. * UI controls should be scaled logarithmically. * * @param leftVolume left volume scalar * @param rightVolume right volume scalar */ /* * FIXME: Merge this into javadoc comment above when setVolume(float) is not @hide. * The single parameter form below is preferred if the channel volumes don't need * to be set independently. */ public void setVolume(float leftVolume, float rightVolume) { baseSetVolume(leftVolume, rightVolume); }
这个东西也是让人醉,很简单的东西,但因为用了传说中ijkplayer框架,对这个框架不熟,然后网上也没有找到相关的设置,搞我的又是去找有这功能的app,又是去反编译,那编译功能还出了bug,又远程到自己家里的电脑再折腾才搞定
==========2017_3_5补:
不知安卓原生就是这样,还是各大厂商埋坑能力确实牛x,setVolume(0)的时候也是会有声音的,不管是audiotrack还是mediaplayer都会有,而且残留的声音大小也是不一样的,有些几乎听不到,有些则完全没用。针对这个问题,mediaplayer可以在setVolume后加再调用meadiaplayer的start()方法,应该又可以处理掉一些厂商的,至少我们这是这样的;audiotrack没有处理过这个问题。
还有如果是声音播放产生的电频作为介质跟硬件交互的话
audiotrack的上述几个参数一定要保持一致,不会电频信号是会有误差的 T T。
领导随口一问,我也就随手一查,感觉pc可以,但手机不一定行
8.bluetoothsocket/bluetoothsocketService 第一次或某一次连接失败的问题
原因:
/** * Get the input stream associated with this socket. * <p>The input stream will be returned even if the socket is not yet * connected, but operations on that stream will throw IOException until * the associated socket is connected. * @return InputStream */ public InputStream getInputStream() throws IOException { return mInputStream; }
百度翻译了一下上面注释的意思,大概的意思是返回的mInputStream可能是在socket还没准备就获取的,如果没有准备好就去read sream 就会返回read fail的错误。
所以我的处理是在socket.getInputStream之前先阻塞500毫秒以保证socket是准备好的。
9.使用YuvImage时出现的内存溢出问题
这段时间在做基于seeta的人脸识别功能。功能实现后跑的时候发现会出现内存溢出的问题。试了半天发现在调用了YuvImage的compressToJpeg方法后,内存并没有自动释放,YuvImage也没有提供可以手动释放的方法,源码最后走的是native层方法,所以只能放弃了。百度半天不行,最后在stackoverflow发现别人早遇到这个问题,并给出方案:
/** * Converts YUV420 NV21 to RGB8888 * * @param data byte array on YUV420 NV21 format. * @param width pixels width * @param height pixels height * @return a RGB8888 pixels int array. Where each int is a pixels ARGB. */ public static int[] convertYUV420_NV21toRGB8888(byte [] data, int width, int height) { int size = width*height; int offset = size; int[] pixels = new int[size]; int u, v, y1, y2, y3, y4; // i percorre os Y and the final pixels // k percorre os pixles U e V for(int i=0, k=0; i < size; i+=2, k+=2) { y1 = data[i ]&0xff; y2 = data[i+1]&0xff; y3 = data[width+i ]&0xff; y4 = data[width+i+1]&0xff; u = data[offset+k ]&0xff; v = data[offset+k+1]&0xff; u = u-128; v = v-128; pixels[i ] = convertYUVtoRGB(y1, u, v); pixels[i+1] = convertYUVtoRGB(y2, u, v); pixels[width+i ] = convertYUVtoRGB(y3, u, v); pixels[width+i+1] = convertYUVtoRGB(y4, u, v); if (i!=0 && (i+2)%width==0) i+=width; } return pixels; } private static int convertYUVtoRGB(int y, int u, int v) { int r,g,b; r = y + (int)(1.402f*v); g = y - (int)(0.344f*u +0.714f*v); b = y + (int)(1.772f*u); r = r>255? 255 : r<0 ? 0 : r; g = g>255? 255 : g<0 ? 0 : g; b = b>255? 255 : b<0 ? 0 : b; return 0xff000000 | (b<<16) | (g<<8) | r; }上面的方法是上面将camera原始帧数据转成正常RGB数据,调用Bitmap.create即可。