在Android7.1上实现一个Native service,通过Parcel的write或setData传递数据,存在字节对齐问题。当字节不对齐会被增加数据或者覆盖掉部分数据。
【Android7.1使用Parcel和java通信读写问题】通过实际测试规律发现,native传递到java,对齐方式如下:
(len-1)%4==0,如此情况,数据可被完整传递到java
(len-1)%4!=0时,最后的(len-1)%4个字节的数据被清0
native通过write传递数据,字节不对齐时,会补0.
demo:
// C++
void JNIMWListener::notify(unsigned int type, void* data, unsigned int len, void* prev)
{
HI_UNUSED(prev);
LOGD("INFO: notify enter type=0x%X (%d)", type, type);
JNIEnv* env = AndroidRuntime::getJNIEnv();
if (NULL == env)
{
return;
}Parcel obj;
int new_len = len;
if((len-1)%4 != 0) {
new_len = len + (4 - (len-1)%4);
} char* dataBuf = new char[new_len];
if(dataBuf == NULL) {
LOGE("no memory.");
return;
} LOGD("len = %dnew_len = %d",len, new_len);
memcpy(dataBuf, data, len);
obj.writeInt32(len);
obj.write(data, new_len);
if (data && len > 0) /* tote extra data*/
{
jobject jParcel = createJavaParcelObject(env);
if (jParcel != NULL)
{
Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
if (NULL == nativeParcel)
{
LOGE("IparcelForJavaObject fail, nativeParcel=NULL");
goto exit;
}nativeParcel->setData(obj.data(), obj.dataSize());
env->CallStaticVoidMethod(mClass, sFields.post_event, mObject, type, 0, 0, jParcel);
env->DeleteLocalRef(jParcel);
}
}
else /* no extra data*/
{
env->CallStaticVoidMethod(mClass, sFields.post_event, mObject, type, 0, 0, NULL);
}if (env->ExceptionCheck()) {
env->ExceptionDescribe();
env->ExceptionClear();
}
exit:
if(dataBuf != NULL) delete[] dataBuf;
}
// java
private IMWListener mMwListener = new IMWListener() {
public void notifyMessage(int messageID, int param1, int param2, Parcel parcel){
switch(messageID) {
case MWMessage.HIMW_EVT_RFID_UID_TO_WIEGAND34:
if(mWeakListener.get() != null) {
if (parcel.dataAvail() <= 0) {
return ;
}int size = parcel.readInt();
int pos = parcel.dataPosition();
Log.d(TAG, "size = : " + size);
int i = 0;
byte[] wiegand34Id = new byte[size];
for(i = 0;
i < size;
i++) {
wiegand34Id[i] = parcel.readByte();
// Log.d(TAG, "wiegand34Id[" + i + "]: " + Integer.toHexString(0xFF & wiegand34Id[i]));
++pos;
parcel.setDataPosition(pos);
}
parcel.recycle();
/*
String mId = null;
try {
mId = new String(wiegand34Id,"GB2312").trim();
Log.d(TAG, "wiegand34Id : " + mId);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
*/
mWeakListener.get().onWiegand34Id(wiegand34Id, size);
}
break;
default:
Log.e(TAG, "meesageID(" + messageID + ") is error.");
}
}
};
经验总结,原理性掌握还需系统学习。
推荐阅读
- Android系统开发|Android Alarm自上而下 调试浅析
- Android系统开发|android ui的几个概念(px,dip(dp),sp,dpi,分辨率等)
- Linux技术|Windows平台下ADB的安装与使用
- Android系统开发|Http协议学习(一)
- Android RTC 自下往上浅析