月光宝盒游戏机大家都了解,但是里面开发流程指导的人比较少,去年本人有幸接到过这样一个项目,研发月光宝盒游戏机。 在过去几年这边积累了非常多的模拟器开发资源。下面是淘宝上一款月光宝盒机器,实际上目前有几个大厂在做,淘宝上爆款一看就了解,我的客户机器比这个还要大一些,需要投币。

可以在网盘下载,app体验:https://pan.baidu.com/s/1c2BdnPY

软件分为2个部分:输入装置+游戏机APP+输出装置。这样就组成一个游戏机系统。

输入装置: 这里主要是按键摇杆, 客户的按键是通过串口实现的,需要我自己去读串口发到我的APP中。

而且客户为了怕设备被破解,串口通信还加了密,真是坑爹啊。

游戏机APP:这里使用的是我 这边街机pro专业版游戏机模拟器,支持拳皇97 98等8000多个游戏。 通过修改,去掉游戏机里面触摸按键,介入上面说的游戏按键。

输出装置:输出装置就是显示器和声音。这些都是走的安卓系统通用api。不需要特殊处理。

这里先贴出串口处理的部分代码:,一般来说摇杆按键走的串口,一般需要经过加密,不然太容易破解了:别人可能盗走你的游戏主板去硬件山寨出一个跟你一模一样的东西。所以这就要涉及加密了。

#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <jni.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>#include "SerialPort.h"
#include "miyao.h"#include "android/log.h"
static const char *TAG="serial_port";
#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO,  TAG, fmt, ##args)
#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args)
#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args)
#define IsLock 1//下函数由叶先生实现/*需要在JNI中实现如下函数功能函数函数功能:将OStar_msg结构加密后转化成字节。
函数目的:(用于java层调用后获得返回字节结果,java层将直接写入到串口。)
char * MsgToByte(OStar_msg msg)函数功能:将字节添加到缓冲区。 若成功返回1,若缓冲区满返回0
函数目的:(用于java层从串口获得字节后调用它将字节保存到缓冲区)
int MsgCacheOffer(char * byte)函数功能:将从缓冲区取出24个有效数据返回,若无返回NULL。(函数需要校验 直到成功取出正确数据)
函数目的:(用于java层调用后,直接从串口取出正确数据)
OStar_msg MsgPoll()*///下函数由softboy实现/*
需要在JNI中实现 Java 层接口函数:函数功能:将java层函数数据转化成 OStar_msg
函数目的:调用MsgToByte转成成字节返回给java。用于发送。调用 MsgToByte();
JNIEXPORT jbyteArray JNICALL Java_org_winplus_serial_utils_SerialPort_msg2byte(JNIEnv *env, jobject thiz,jint msg1,jint msg2,jint msg3)函数功能:将java层从串口读出的字节调用MsgCacheOffer 写入到缓冲区
函数目的:java层串口读取字节 ,调用 MsgCacheOffer();
JNIEXPORT jbyteArray JNICALL Java_org_winplus_serial_utils_SerialPort_msg2cache(JNIEnv *env, jobject thiz,jbyteArray bytes)函数功能:将java层从串口读出的字节调用MsgCacheOffer 写入到缓冲区
函数目的:java串口读取有效数据 ,调用 MsgPoll()
JNIEXPORT jobject JNICALL Java_org_winplus_serial_utils_SerialPort_msg2java(JNIEnv *env, jobject thiz)*/static speed_t getBaudrate(jint baudrate)
{switch (baudrate){case 0: return B0;case 50: return B50;case 75: return B75;case 110: return B110;case 134: return B134;case 150: return B150;case 200: return B200;case 300: return B300;case 600: return B600;case 1200: return B1200;case 1800: return B1800;case 2400: return B2400;case 4800: return B4800;case 9600: return B9600;case 19200: return B19200;case 38400: return B38400;case 57600: return B57600;case 115200: return B115200;case 230400: return B230400;case 460800: return B460800;case 500000: return B500000;case 576000: return B576000;case 921600: return B921600;case 1000000: return B1000000;case 1152000: return B1152000;case 1500000: return B1500000;case 2000000: return B2000000;case 2500000: return B2500000;case 3000000: return B3000000;case 3500000: return B3500000;case 4000000: return B4000000;default: return B9600;}
}typedef unsigned long  u32;
typedef unsigned short u16;
typedef unsigned char  u8;#define JIAOME_LEN 18 //加密长度typedef struct CMD_group1
{u8 CMD;u8 rand1;
}CMD_group;typedef struct OStar_msg1
{union{u8 tbyte[16];u16  tword[8];u32 tdword[4];}data;CMD_group CMD_g;struct{u8 xuliehao1;u8 xuliehao2;u8 verify;u8 Align[3];}verf;
}OStar_msg;typedef union
{long d32;char d8[4];
}U32data;long Big_Lit_chang_32(long dat)
{U32data a,b;a.d32=dat;b.d8[0]=a.d8[3];b.d8[1]=a.d8[2];b.d8[2]=a.d8[1];b.d8[3]=a.d8[0];return b.d32;
}typedef union
{unsigned short d16;unsigned char d8[2];
}U16data;unsigned short Big_Lit_chang_16(unsigned short dat)
{U16data a,b;a.d16=dat;b.d8[0]=a.d8[1];b.d8[1]=a.d8[0];    return b.d16;
}#define GetItemSum( XX )   (sizeof(XX)/sizeof(XX[0]))#define   R_PUSH_BUFF_INT(_NAME, XXX) do{\_NAME ## _flag ++; _NAME ## _buff[_NAME ## _in] = XXX;   \if(_NAME ## _in >= GetItemSum(_NAME ## _buff)-1) _NAME ## _in = 0;    \else _NAME ## _in++;}while(0)#define R_POP_BUFF_INT(_NAME, XXX) do{  \XXX = _NAME ## _buff[_NAME ## _out];  \_NAME ## _flag --; \if(_NAME ## _out >= GetItemSum(_NAME ## _buff) -1) _NAME ## _out =0; \else _NAME ## _out++;}while(0)#define MAX_BUFF 512u32 USART_rece_in=0;
u32 USART_rece_out=0;
u32 USART_rece_flag=0;
u8  USART_rece_buff[MAX_BUFF];u32 usart_err=0;
int MsgCacheOffer(char *byte,int len)
{   int i = 0;for (i=0;i<len;i++){if (USART_rece_flag>=MAX_BUFF){usart_err++;LOGD("jni MsgCacheOffer called errors:%d",usart_err);return 0;   }R_PUSH_BUFF_INT(USART_rece,(byte[i]&0xff));}return len;
}void OutdataToBuff(u8 *dat,u32 len)
{u8 i;for (i=0;i<len;i++){dat[i] = USART_rece_buff[(i+USART_rece_out)%sizeof(USART_rece_buff)];}
}void Dele_USART3_rece(u16 index)
{USART_rece_flag -= index;USART_rece_out += index;USART_rece_out = USART_rece_out%GetItemSum(USART_rece_buff);
}  u32 get_random_num(u32 max)
{u32 sum=0;sum = rand()+10000;return sum%max;
}u8 deal_lock_miyao(u8 *dat,u8 xuliehao1,u8 xuliehao2)
{u8 i,veriy;
#if IsLockfor (i=0;i<JIAOME_LEN;i++)dat[i] ^=xuliehao1;
#endif  for (i=1,veriy=dat[0];i<JIAOME_LEN;i++)//中间这一层校验,增加隐蔽性veriy ^=dat[i];
#if IsLock  for (i=0;i<JIAOME_LEN;i++){dat[i] ^= miyao1[xuliehao1][i];dat[i] ^= miyao2[xuliehao2][i];//LOGD("deal_lock_miyao called dat %02d:%02x",i,dat[i]);}
#endif          //LOGD("jni deal_lock_miyao called verify:%d",veriy);return veriy;
}u8 deal_Unlock_miyao(u8 *dat,u8 xuliehao1,u8 xuliehao2)
{u8 i,veriy;
#if IsLock  for (i=0;i<JIAOME_LEN;i++){dat[i] ^= miyao1[xuliehao1][i];dat[i] ^= miyao2[xuliehao2][i];}
#endiffor (i=1,veriy=dat[0];i<JIAOME_LEN;i++)//中间这一层校验,增加隐蔽性veriy ^=dat[i];
#if IsLock  for (i=0;i<JIAOME_LEN;i++)dat[i] ^=xuliehao1;
#endifreturn veriy;
}void dealMsg(OStar_msg  msg1,JNIEnv *env, jobject thiz);
OStar_msg MsgPoll(JNIEnv *env, jobject thiz)
{OStar_msg msg;u8 temp;u8 Valcrc;while (1){if (USART_rece_flag<24)return msg;memset((u8 *)&msg,0,sizeof(msg));OutdataToBuff((u8 *)&msg,24);//DecryptData((u8 *)&msg, (u8 *)&msg, sizeof(msg));//LOGD("jni MsgPoll called %d",sizeof(msg));//看是不是一个包,不是直接处理,省了校验的运算if (msg.verf.Align[0]!=0xff||msg.verf.Align[1]!=0xfa||msg.verf.Align[2]!=0xfb){R_POP_BUFF_INT(USART_rece,temp);usart_err++;LOGD("jni MsgPoll called msg.verf.Feat!=0xd3 errors:%d",usart_err);continue;}Valcrc=deal_Unlock_miyao((u8 *)&msg,msg.verf.xuliehao1,msg.verf.xuliehao2);if (Valcrc==msg.verf.verify){int i = 0;//for(i =0;i<24;i++){//   LOGD("jni MsgPoll CMD_OStar_getFlash OStar_msg,%d: %x",i,*((u8* )&msg+i));//}dealMsg(msg,env,thiz);Dele_USART3_rece(24);return msg;} else{usart_err++;R_POP_BUFF_INT(USART_rece,temp);LOGD("jni MsgPoll called errors:%d",usart_err);}}
}
//
//char *MsgToByte(OStar_msg msg)
//{
//  msg.verf.Align[0]=0xff;
//  msg.verf.Align[1]=0xfa;
//  msg.verf.Align[2]=0xfb;
//  msg.verf.xuliehao1=get_random_num(0xff);
//  msg.verf.xuliehao2=get_random_num(0xff);
//  msg.verf.verify=deal_lock_miyao((u8 *)&msg,msg.verf.xuliehao1,msg.verf.xuliehao2);
//
//  //u8 *p=(u8*)&msg;
//  //int i =0;
//  //for(i=0;i<24;i++){
//      //LOGD("jni MsgToByte called %02d:%02x",i,p[i]);
//  //}
//
//  return(char *)&msg;
//}void MsgToByteAndWrite(OStar_msg msg,int fdcom)
{msg.verf.Align[0]=0xff;msg.verf.Align[1]=0xfa;msg.verf.Align[2]=0xfb;msg.verf.xuliehao1=get_random_num(0xff);msg.verf.xuliehao2=get_random_num(0xff);msg.verf.verify=deal_lock_miyao((u8 *)&msg,msg.verf.xuliehao1,msg.verf.xuliehao2);//u8 *p=(u8*)&msg;//int i =0;//for(i=0;i<24;i++){//LOGD("jni MsgToByte called %02d:%02x",i,p[i]);//}if(fdcom != -1)write(fdcom, (char *)&msg, 24);
}/** Class:     android_serialport_SerialPort* Method:    open* Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor;*/
static int static_fd = -1;
static int inited = -1;
jclass dpclazz_key;
jmethodID method_key;
JNIEXPORT jobject JNICALL Java_org_winplus_serial_utils_SerialPort_open
(JNIEnv *env, jclass thiz, jstring path, jint baudrate, jint flags)
{speed_t speed;jobject mFileDescriptor;/* Check arguments */{speed = getBaudrate(baudrate);if (speed == -1){/* TODO: throw an exception */LOGE("Invalid baudrate");return NULL;}}int fd =-1;/* Opening device */{jboolean iscopy;const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy);LOGD("Opening serial port %s with flags 0x%x", path_utf, O_RDWR | flags);fd = open(path_utf, O_RDWR | flags);LOGD("open() fd = %d", fd);(*env)->ReleaseStringUTFChars(env, path, path_utf);if (fd == -1){/* Throw an exception */LOGE("Cannot open port");/* TODO: throw an exception */return NULL;}}/* Configure device */{struct termios cfg;LOGD("Configuring serial port");if (tcgetattr(fd, &cfg)){LOGE("tcgetattr() failed");close(fd);/* TODO: throw an exception */return NULL;}cfmakeraw(&cfg);cfsetispeed(&cfg, speed);cfsetospeed(&cfg, speed);if (tcsetattr(fd, TCSANOW, &cfg)){LOGE("tcsetattr() failed");close(fd);/* TODO: throw an exception */return NULL;}}static_fd = fd;/* Create a corresponding file descriptor */{jclass cFileDescriptor = (*env)->FindClass(env, "java/io/FileDescriptor");jmethodID iFileDescriptor = (*env)->GetMethodID(env, cFileDescriptor, "<init>", "()V");jfieldID descriptorID = (*env)->GetFieldID(env, cFileDescriptor, "descriptor", "I");mFileDescriptor = (*env)->NewObject(env, cFileDescriptor, iFileDescriptor);(*env)->SetIntField(env, mFileDescriptor, descriptorID, (jint)fd);}dpclazz_key= (*env)->FindClass(env,"org/winplus/serial/utils/SerialPort");if (dpclazz_key==0){LOGD("find class error");return;}method_key = (*env)->GetStaticMethodID(env,dpclazz_key,"onKey","(III)V");if (method_key==0){LOGD("find onKeyValue error");return;}return mFileDescriptor;
}/** Class:     cedric_serial_SerialPort* Method:    close* Signature: ()V*/
JNIEXPORT void JNICALL Java_org_winplus_serial_utils_SerialPort_close
(JNIEnv *env, jobject thiz)
{jclass SerialPortClass = (*env)->GetObjectClass(env, thiz);jclass FileDescriptorClass = (*env)->FindClass(env, "java/io/FileDescriptor");jfieldID mFdID = (*env)->GetFieldID(env, SerialPortClass, "mFd", "Ljava/io/FileDescriptor;");jfieldID descriptorID = (*env)->GetFieldID(env, FileDescriptorClass, "descriptor", "I");jobject mFd = (*env)->GetObjectField(env, thiz, mFdID);jint descriptor = (*env)->GetIntField(env, mFd, descriptorID);static_fd = -1;inited = -1;LOGD("close(fd = %d)", descriptor);close(descriptor);
}JNIEXPORT void  JNICALL Java_org_winplus_serial_utils_SerialPort_msg2cache
(JNIEnv *env, jobject thiz,jbyteArray pcmData,jint len){jbyte *pcm;jboolean isCopy = 0;pcm = (*env)->GetByteArrayElements(env,pcmData, 0);int ret = MsgCacheOffer(pcm,len);//LOGD("jni msg2cache len:%d",ret);(*env)->ReleaseByteArrayElements(env,pcmData, pcm, JNI_ABORT);
}int PortSend(int fdcom, char *data, int datalen)
{ return write(fdcom, data, datalen);
} enum CMD_2android //stm发给android
{CMD_OStar_Key = 0xA1,CMD_OStar_TuiB = 0x5f,CMD_OStar_GetInfo = 0x12,CMD_OStar_ErrorInfo = 0x11,CMD_OStar_ShakeHand = 0x23,CMD_OStar_BackFlsh,CMD_OStar_BackOK,
};enum CMD_2STM32   //android发给stm
{CMD2STM32_tuiBi,CMD2STM32_tuiCP,CMD2STM32_GetMacInfo,CMD2STM32_ResetSTM,CMD2STM32_ShakeHand,CMD2STM32_Ask_ShakeHand,CMD2STM32_AskFlsh,CMD2STM32_SaveOneFlsh,CMD2STM32_TuiBPinit,CMD2STM32_end = 0xff
};const u32 MaskBits[32]
={0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80,(0x1UL<<8), (0x1UL<<9), (0x1UL<<10), (0x1UL<<11),(0x1UL<<12), (0x1UL<<13), (0x1UL<<14), (0x1UL<<15),(0x1UL<<16), (0x1UL<<17), (0x1UL<<18), (0x1UL<<19),(0x1UL<<20), (0x1UL<<21), (0x1UL<<22), (0x1UL<<23),(0x1UL<<24), (0x1UL<<25), (0x1UL<<26), (0x1UL<<27),(0x1UL<<28), (0x1UL<<29), (0x1UL<<30), (0x1UL<<31),
};#define KeyDowndelay 1
#define KeyUpdelay   1
#define MAX_SLAVE 2int OTHER_KEY_START = 15;int FUNC_KEY_START = 20;enum{MenuKey_None,MenuKey_Down,MenuKey_OK,MenuKey_SGame,MenuKey_Right,MenuKey_Left,MenuKey_No,MenuKey_Up,MenuKey_Count,};u8 meun_key_flag=0Xff;u8 meun_key=0Xff;#define MenuKeyDownDelay 1#define MenuKeyUpDelay 3u8 meunkeydelay[8];void DealMeunKey(JNIEnv *env, jobject thiz){u8 i,newflag,oldflag;for (i=0;i<MenuKey_Count;i++){newflag=meun_key&MaskBits[i];oldflag=meun_key_flag&MaskBits[i];if (newflag!=oldflag){meunkeydelay[i]++;if (!newflag){if (meunkeydelay[i]>MenuKeyDownDelay){meunkeydelay[i]=0;meun_key_flag&=~MaskBits[i];//有键按下LOGD("jni DealMeunKey 1 CMD_OStar_Key down:%d ",i);(*env)->CallStaticVoidMethod(env,dpclazz_key,method_key,i+FUNC_KEY_START,1,0);}} else{if (meunkeydelay[i]>MenuKeyUpDelay){meunkeydelay[i]=0;meun_key_flag|=MaskBits[i];//按键弹起LOGD("jni DealMeunKey 1 CMD_OStar_Key down:%d ",i);(*env)->CallStaticVoidMethod(env,dpclazz_key,method_key,i+FUNC_KEY_START,0,0);}}} else{meunkeydelay[i]=0;}}}enum
{play_start,play_button3,play_button1,play_button2,play_right,play_left,play_down,play_up,play_button4,play_button5,play_button6,play_cnt,
};u16 orgKeyflag[MAX_SLAVE] ={ 0xffff, 0xffff};
u16 doKeyflag[MAX_SLAVE] = { 0xffff, 0xffff};
u16 Key_delay[MAX_SLAVE][play_cnt] = { 0, 0};void Do_Key(JNIEnv *env, jobject thiz)
{int i, id, orgflag, doflag;for (id = 0; id <MAX_SLAVE; id++){if (orgKeyflag[id] == doKeyflag[id]){memset((char *)&Key_delay[id],0,sizeof(Key_delay[id]));continue;}for (i = 0; i < play_cnt; i++){orgflag = orgKeyflag[id] & MaskBits[i];doflag =  doKeyflag[id] & MaskBits[i];if (orgflag != doflag){Key_delay[id][i]++;if (!orgflag){if (Key_delay[id][i]>KeyDowndelay){Key_delay[id][i] = 0;doKeyflag[id] &= ~MaskBits[i];//按键按下LOGD("jni Do_Key 1 CMD_OStar_Key down:%d ,player is:%d",i,id);(*env)->CallStaticVoidMethod(env,dpclazz_key,method_key,i,1,id);}} else{if (Key_delay[id][i]>KeyUpdelay){Key_delay[id][i] = 0;doKeyflag[id] |= MaskBits[i];//按键弹起LOGD("jni Do_Key 1 CMD_OStar_Key up:%d ,player is:%d",i);(*env)->CallStaticVoidMethod(env,dpclazz_key,method_key,i,0,id);}}} else{Key_delay[id][i] = 0;}}}
}//投币数
int ToubiCnt[MAX_SLAVE]={0,0};void dealMsg(OStar_msg  msg,JNIEnv *env, jobject thiz){unsigned int i=0;jclass dpclazz;jmethodID method;    LOGD("jni dealMsg called get msg,cmd:%d,errors:%d",msg.CMD_g.CMD,usart_err);OStar_msg data;int id=0;switch (msg.CMD_g.CMD){case CMD_OStar_ShakeHand:inited = 0;memset((unsigned char* )&data,0,sizeof(data));data.data.tdword[0]=msg.data.tdword[0];data.CMD_g.CMD=CMD2STM32_ShakeHand;MsgToByteAndWrite(data,static_fd);LOGD("jni dealMsg  CMD_OStar_ShakeHand static_fd %d",static_fd);break;case CMD_OStar_Key:orgKeyflag[0]=msg.data.tbyte[0];orgKeyflag[1]=msg.data.tbyte[1];if (msg.data.tbyte[6]&MaskBits[0])orgKeyflag[0]|=MaskBits[8];else orgKeyflag[0]&=~MaskBits[8];if (msg.data.tbyte[6]&MaskBits[1])orgKeyflag[1]|=MaskBits[8];else orgKeyflag[1]&=~MaskBits[8];if (msg.data.tbyte[6]&MaskBits[2])orgKeyflag[0]|=MaskBits[9];else orgKeyflag[0]&=~MaskBits[9];if (msg.data.tbyte[6]&MaskBits[3])orgKeyflag[0]|=MaskBits[10];else orgKeyflag[0]&=~MaskBits[10];if (msg.data.tbyte[6]&MaskBits[4])orgKeyflag[1]|=MaskBits[9];else orgKeyflag[1]&=~MaskBits[9];if (msg.data.tbyte[6]&MaskBits[5])orgKeyflag[1]|=MaskBits[10];else orgKeyflag[1]&=~MaskBits[10];Do_Key(env,thiz);for (id=0;id<MAX_SLAVE;id++){if (msg.data.tbyte[7+id]>0){//正在投币中ToubiCnt[id]+=msg.data.tbyte[7+id];LOGD("jni dealMsg  coin player: %d , total:%d ,add:%d",id,ToubiCnt[id],msg.data.tbyte[7+id]);(*env)->CallStaticVoidMethod(env,dpclazz_key,method_key,OTHER_KEY_START,msg.data.tbyte[7+id],id);}}meun_key = msg.data.tbyte[13];DealMeunKey(env,thiz);break;case CMD_OStar_GetInfo:LOGD("jni dealMsg  CMD_OStar_GetInfo 0 %d",msg.data.tdword[0]);LOGD("jni dealMsg  CMD_OStar_GetInfo 1 %d",msg.data.tdword[1]);LOGD("jni dealMsg  CMD_OStar_GetInfo 2 %d",msg.data.tdword[2]);LOGD("jni dealMsg  CMD_OStar_GetInfo 3 %d",msg.data.tdword[3]);break;case CMD_OStar_ErrorInfo:for (id=0;id<MAX_SLAVE;id++){if (msg.data.tbyte[id] & MaskBits[0]){//显示:投币固障(*env)->CallStaticVoidMethod(env,dpclazz_key,method_key,OTHER_KEY_START+1,0,0);} else{//清除投币固障(*env)->CallStaticVoidMethod(env,dpclazz_key,method_key,OTHER_KEY_START+2,0,0);}}break;}
}JNIEXPORT jobject JNICALL Java_org_winplus_serial_utils_SerialPort_msg2java
(JNIEnv *env, jobject thiz){MsgPoll(env,thiz);
}JNIEXPORT jint JNICALL Java_org_winplus_serial_utils_SerialPort_msginit
(JNIEnv *env, jobject thiz){OStar_msg  data;memset((unsigned char* )&data,0,sizeof(data));if (inited == 0){LOGD("jni msginit called CMD2STM32_GetMacInfo");    data.CMD_g.CMD=CMD2STM32_GetMacInfo;MsgToByteAndWrite(data,static_fd);inited = 1; } else if (inited == -1){LOGD("jni msginit called CMD2STM32_Ask_ShakeHand");data.CMD_g.CMD = CMD2STM32_Ask_ShakeHand;MsgToByteAndWrite(data,static_fd);} else if (inited == 1){}//LOGD("jni msginit called %d:",inited);return inited;
}

android安卓月光宝盒项目源码技术讲解相关推荐

  1. 安卓月光宝盒项目源码讲解

    这里使用的是MAME 模拟器,当前手头实现了全部模拟器,FBA MD FC PSP PS1 ,支持拳皇97 98等8000多个游戏. 通过修改,去掉游戏机里面触摸按键,介入上面说的游戏按键. 输入设备 ...

  2. 140款Android开源优秀项目源码

    140款Android开源优秀项目源码 BeautifulRefreshLayout-漂亮的美食下拉刷新 https://github.com/android-cjj/BeautifulRefresh ...

  3. Android安卓麻将识别源码Demo( 三)

    Android安卓麻将识别源码Demo( 三) 未经过允许不得转载,转载请联系我,如何联系,点我头像. 连载已经完结, 百度网盘测试APP下载地址:  链接:https://pan.baidu.com ...

  4. Android开源优秀项目源码

    本文由 简悦 SimpRead 转码, 原文地址 blog.csdn.net BeautifulRefreshLayout - 漂亮的美食下拉刷新 https://github.com/android ...

  5. Android 140款Android开源优秀项目源码

    BeautifulRefreshLayout-漂亮的美食下拉刷新 https://github.com/android-cjj/BeautifulRefreshLayout/tree/Beautifu ...

  6. 155款安卓开源项目源码整理,总有你要找的

    https://www.jianshu.com/p/a0dd06565747 1.BeautifulRefreshLayout-漂亮的美食下拉刷新 https://github.com/android ...

  7. 安卓期末项目源码_手机随时随地写Python,还可以开发安卓APP,太厉害了!

    python, 近五年最为火爆的编程语言,语法优雅,类库丰富,一行代码即可完成 Java 十行代码量. 本次,舞剑来推荐一款手机端使用 Python 的APP. QPython QPython是安卓上 ...

  8. 基于springboot二手车评估系统设计与实现.rar(论文+项目源码+技术文档说明+ppt答辩)

    1 绪论 1 1.1研究背景与意义 1 1.2研究现状 1 1.3论文结构 2 2 系统开发工具和技术 3 2.1 系统开发工具 3 2.1.1 IDEA简介 3 2.2 系统开发技术 3 2.2.1 ...

  9. 重磅!《Android 全埋点技术白皮书》开源所有项目源码!

    随着大数据行业的快速发展,越来越多的人们意识到--数据基础夯实与否,取决于数据的采集方式. 目前,国内大数据埋点方式多样,按照埋点位置不同,可以分为前端(客户端)埋点与后端(服务器端)埋点.其中全埋点 ...

最新文章

  1. datatable 前台和后台数据格式
  2. 热烈欢呼:cnblogs.com博客园首页通过W3C验证
  3. 10分钟搞懂:亿级用户的分布式数据存储解决方案
  4. React AntD 表格查看修改时默认选中几行数据
  5. sql server 2005 数据库状态 变成 可疑的解决方案
  6. Python中的序列操作
  7. js理解 call( ) | apply( ) | caller( ) | callee( )
  8. PHP7不能用string类名,解决thinkphp php7 Cannot use ‘String’ as class name as it is reserved...
  9. linux mint 安装java_Linux mint 安装步骤
  10. Selenium2.0功能测试之唯一元素的定位
  11. HDU 1133 Buy the Ticket
  12. 在线文本比较工具(用来对比两个代码文件差异的地方)
  13. 可以搜python题答案的app-可以搜Python题答案的APP有哪些?
  14. (Windows12)DHCP服务器的搭建
  15. The Simplest Classifier: Histogram Comparison (最简单的分类器:直方图比较)
  16. 神技能:Python控制键盘鼠标
  17. Java 解析复杂表格excel
  18. 移动电影院开启5G全新征程
  19. 从 Angular Component 和 Directive 的实例化,谈谈 Angular forRoot 方法的命令由来
  20. 30岁后再转行程序员,能行吗?

热门文章

  1. 什么是云计算里的负载均衡CLB?
  2. Z字形变换(C++)
  3. sklearn scikit-learn
  4. Python 函数的定义和使用
  5. MySql高级部分<二>
  6. 机器人三种类型的停止
  7. 廊坊职业技术学院计算机科学与工程系,计算机科学与工程系“云计算技术与应用”国赛获奖...
  8. 学习SpringBoot 集成邮件发送(参考纯洁的微笑) 记录其中遇到的问题
  9. Webpack-2:Webpack
  10. linux修改主机名(永久)