diff --git a/README.md b/README.md index af9dfe9..02ae71d 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,2 @@ -# venue_android - -#### 介绍 -Android - -#### 软件架构 -软件架构说明 - - -#### 安装教程 - -1. xxxx -2. xxxx -3. xxxx - -#### 使用说明 - -1. xxxx -2. xxxx -3. xxxx - -#### 参与贡献 - -1. Fork 本仓库 -2. 新建 Feat_xxx 分支 -3. 提交代码 -4. 新建 Pull Request - - -#### 码云特技 - -1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md -2. 码云官方博客 [blog.gitee.com](https://blog.gitee.com) -3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解码云上的优秀开源项目 -4. [GVP](https://gitee.com/gvp) 全称是码云最有价值开源项目,是码云综合评定出的优秀开源项目 -5. 码云官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) -6. 码云封面人物是一档用来展示码云会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) +# SmartVenue_Android_App +This is a repo for hosting android application of smartvenue project. diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..fb2d5a4 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,99 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "com.ydd.sportfaceid" + minSdkVersion 19 + targetSdkVersion 28 + versionCode 4 + versionName "1.3" + flavorDimensions "versionCode" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + + android { + lintOptions { + abortOnError false + } + compileOptions { + sourceCompatibility 1.8 + targetCompatibility 1.8 + } + } + + + signingConfigs { + release { + keyAlias 'faceid' + keyPassword '123456' + storeFile file('../faceid.jks') + storePassword '123456' + } + } + + buildTypes { + release { + minifyEnabled false + signingConfig signingConfigs.release + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + productFlavors { + + product { + /** + * 服务器连接 + */ + buildConfigField("String", "SERVER_IP", "\"120.27.209.4\"") + buildConfigField("String", "SERVER_PORT", "\"56791\"") +// buildConfigField("String", "SERVER_IP", "\"192.168.1.200\"") +// buildConfigField("String", "SERVER_PORT", "\"56794\"") + /** + * face++连接地址 + */ + buildConfigField("String", "FACEID_WS_URL", "\"ws://192.168.1.111:9000/video?url=\"") + + /** + * 门禁连接地址 + */ + buildConfigField("String", "DOOR_SERVER_IP", "\"192.168.1.150\"") + buildConfigField("String", "DOOR_SERVER_PORT", "\"8000\"") + + buildConfigField("String", "DOOR_SN", "\"MC-5824T28085603\"") + buildConfigField("String", "DOOR_PWD", "\"FFFFFFFF\"") + } + } +} + +repositories { + flatDir { + dirs 'libs' + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation 'com.google.code.gson:gson:2.8.4' + implementation 'com.squareup.okhttp3:okhttp:3.3.1' + implementation 'io.netty:netty-all:4.1.17.Final' + implementation 'org.greenrobot:eventbus:3.1.1' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + implementation 'com.jakewharton:butterknife:8.8.1' + annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' + implementation 'io.reactivex:rxjava:1.2.4' + implementation 'io.reactivex:rxandroid:1.2.1' + implementation 'de.hdodenhof:circleimageview:2.2.0' + implementation('com.github.bumptech.glide:glide:4.8.0') { + exclude group: "com.android.support" + } + implementation 'de.mrmaffen:libvlc-android:2.1.12@aar' + implementation "org.java-websocket:Java-WebSocket:1.4.0" + compile 'com.tencent.bugly:crashreport:latest.release' + +} diff --git a/app/libs/FCardIO.jar b/app/libs/FCardIO.jar new file mode 100644 index 0000000..d62d2f8 Binary files /dev/null and b/app/libs/FCardIO.jar differ diff --git a/app/product/debug/output.json b/app/product/debug/output.json new file mode 100644 index 0000000..2472802 --- /dev/null +++ b/app/product/debug/output.json @@ -0,0 +1 @@ +[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"app-product-debug.apk","fullName":"productDebug","baseName":"product-debug"},"path":"app-product-debug.apk","properties":{}}] \ No newline at end of file diff --git a/app/product/release/output.json b/app/product/release/output.json new file mode 100644 index 0000000..7825f59 --- /dev/null +++ b/app/product/release/output.json @@ -0,0 +1 @@ +[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"app-product-release.apk","fullName":"productRelease","baseName":"product-release"},"path":"app-product-release.apk","properties":{}}] \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/androidTest/java/com/ydd/sportfaceid/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/ydd/sportfaceid/ExampleInstrumentedTest.java new file mode 100644 index 0000000..3cd7f3c --- /dev/null +++ b/app/src/androidTest/java/com/ydd/sportfaceid/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.ydd.sportfaceid; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("com.ydd.sportfaceid", appContext.getPackageName()); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..2580683 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/ydd/sportfaceid/MainActivity.java b/app/src/main/java/com/ydd/sportfaceid/MainActivity.java new file mode 100644 index 0000000..2bbfd35 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/MainActivity.java @@ -0,0 +1,593 @@ +package com.ydd.sportfaceid; + +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; +import android.net.Uri; +import android.os.CountDownTimer; +import android.os.Handler; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.text.TextUtils; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.SurfaceView; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.bumptech.glide.Glide; +import com.tencent.bugly.Bugly; +import com.tencent.bugly.crashreport.CrashReport; +import com.ydd.sportfaceid.config.SDAppConfig; +import com.ydd.sportfaceid.event.FaceidEvent; +import com.ydd.sportfaceid.event.MessageEvent; +import com.ydd.sportfaceid.main.SDBaseActivity; +import com.ydd.sportfaceid.net.ClientThread; +import com.ydd.sportfaceid.net.dto.MemberDto; +import com.ydd.sportfaceid.service.ClientService; +import com.ydd.sportfaceid.setting.SDSettingActivity; +import com.ydd.sportfaceid.utils.EggClickUtil; +import com.ydd.sportfaceid.websocket.FaceWsClient; +import com.ydd.sportfaceid.websocket.FaceWsClientService; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; +import org.videolan.libvlc.IVLCVout; +import org.videolan.libvlc.LibVLC; +import org.videolan.libvlc.Media; +import org.videolan.libvlc.MediaPlayer; + +import java.util.ArrayList; + +import butterknife.BindView; +import butterknife.OnClick; +import de.hdodenhof.circleimageview.CircleImageView; + +public class MainActivity extends SDBaseActivity implements IVLCVout.OnNewVideoLayoutListener { + + private final String TAG = "MainActivity"; + + public final int welcome_show = 10; + + public final int user_info_ok = 11; + + public final int user_info_fail = 12; + + public final int user_info_out_ok = 13; + + public final int user_info_recahrge = 14; + + @BindView(R.id.welcome_layout) + LinearLayout welcome_layout; + + @BindView(R.id.welcome_label) + TextView welcome_label; + + @BindView(R.id.topInfoTextView) + TextView topInfoTextView; + + @BindView(R.id.user_avator) + CircleImageView avator_imageview; + + @BindView(R.id.user_name_label) + TextView user_name_label; + + @BindView(R.id.user_phone_label) + TextView user_phone_label; + + @BindView(R.id.user_amount_label) + TextView user_amount_label; + + @BindView(R.id.faceid_video_view) + SurfaceView faceid_video_view; + + @BindView(R.id.sb_string_label) + TextView sb_string_label; + + @BindView(R.id.count_down_label) + TextView count_down_label; + + + @BindView(R.id.userInfoLayout) + LinearLayout userInfoLayout; + + @BindView(R.id.package_name_label) + TextView package_name_label; + + @BindView(R.id.user_place_label) + TextView user_place_label; + + @BindView(R.id.memberInfoLineView) + LinearLayout memberInfoLineView; + + @BindView(R.id.memberInfopackLayout) + LinearLayout memberInfopackLayout; + + @BindView(R.id.unit_price_layout) + LinearLayout unit_price_layout; + + @BindView(R.id.unit_price_label) + TextView unit_price_label; + + @BindView(R.id.unit_price_line_view) + LinearLayout unit_price_line_view; + + public int current_status; + + public CountDownTimer countDownTimer; + + public CountDownTimer firstCountDownTimer; + + public EggClickUtil eggClickUtil; + + public void setMaxCountDownTime(int maxCountDownTime) { + if (maxCountDownTime < 0) { + return; + } + this.maxCountDownTime = maxCountDownTime; + count_down_label.setVisibility(View.VISIBLE); + String downString = String.format("请注意门禁将于 %ds 后关闭", this.maxCountDownTime); + count_down_label.setText(downString); + } + + public static final int maxTime = 15; + public int maxCountDownTime = 15; + + private static final int SURFACE_BEST_FIT = 0; + private static final int SURFACE_FIT_SCREEN = 1; + private static final int SURFACE_FILL = 2; + private static final int SURFACE_16_9 = 3; + private static final int SURFACE_4_3 = 4; + private static final int SURFACE_ORIGINAL = 5; + private static int CURRENT_SIZE = SURFACE_4_3; + + + private final Handler mHandler = new Handler(); + private LibVLC mLibVLC = null; + private MediaPlayer mMediaPlayer = null; + private int mVideoHeight = 0; + private int mVideoWidth = 0; + private int mVideoVisibleHeight = 0; + private int mVideoVisibleWidth = 0; + private int mVideoSarNum = 0; + private int mVideoSarDen = 0; + + private View.OnLayoutChangeListener mOnLayoutChangeListener = null; + + private SDErrorDialog errorDialog; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + //不做什么事情,只是计算屏幕的高宽 + initScreen(); + //注册消息bus + EventBus.getDefault().register(this); + + //初始化视频播放 + final ArrayList args = new ArrayList<>(); +// args.add("--aout=opensles"); +// args.add("--audio-time-stretch"); + args.add("-vvv"); + mLibVLC = new LibVLC(this, args); + mMediaPlayer = new MediaPlayer(mLibVLC); + + configView(); + + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + + //启动Service + Intent socketService = new Intent(this, ClientService.class); + startService(socketService); + } + + @Override + protected void onResume() { + super.onResume(); + StartApplication.executor.execute(new Runnable() { + @Override + public void run() { + startPlay(); + } + }); + + } + + public void startPlay() { + final IVLCVout vlcVout = mMediaPlayer.getVLCVout(); + vlcVout.setVideoView(faceid_video_view); + vlcVout.attachViews(this); + + String media_url = SDAppConfig.getInstance().getCurrentCameraUrl(); + Media media = new Media(mLibVLC, Uri.parse(media_url)); + + mMediaPlayer.setEventListener(new MediaPlayer.EventListener() { + @Override + public void onEvent(MediaPlayer.Event event) { +// Log.d("MediaPlayer", "onEvent: " + String.valueOf(event.type)); + if (event.type == MediaPlayer.Event.EndReached) { +// Log.d("MediaPlayer", "onEvent: MediaPlayer.Event.EndReached"); + mMediaPlayer.setMedia(media); + mMediaPlayer.play(); + } + } + }); + mMediaPlayer.setMedia(media); + media.release(); + mMediaPlayer.play(); + + if (mOnLayoutChangeListener == null) { + mOnLayoutChangeListener = new View.OnLayoutChangeListener() { + private final Runnable mRunnable = new Runnable() { + @Override + public void run() { + updateVideoSurfaces(); + } + }; + + @Override + public void onLayoutChange(View v, int left, int top, int right, + int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { + if (left != oldLeft || top != oldTop || right != oldRight || bottom != oldBottom) { + mHandler.removeCallbacks(mRunnable); + mHandler.post(mRunnable); + } + } + }; + } + } + + private void initScreen() { + WindowManager manager = getWindowManager(); + DisplayMetrics outMetrics = new DisplayMetrics(); + manager.getDefaultDisplay().getMetrics(outMetrics); + int mScreenW = outMetrics.widthPixels; + int mScreenH = outMetrics.heightPixels; + + Log.d("sander", mScreenW + "==== " + mScreenH); + } + + public void setCurrentStatus(int current_status) { + this.current_status = current_status; + this.sb_string_label.setVisibility(View.GONE); + this.unit_price_layout.setVisibility(View.GONE); + this.unit_price_line_view.setVisibility(View.GONE); + if (this.current_status == welcome_show) { + this.count_down_label.setVisibility(View.GONE); + this.welcome_layout.setVisibility(View.VISIBLE); + this.welcome_label.setVisibility(View.GONE); + this.topInfoTextView.setText(getResources().getString(R.string.top_line_info1)); + } else { + this.welcome_layout.setVisibility(View.GONE); + this.welcome_label.setVisibility(View.VISIBLE); + } + if (this.current_status == user_info_fail){ + this.sb_string_label.setVisibility(View.VISIBLE); + } + + if (this.current_status == user_info_ok || this.current_status == user_info_fail || this.current_status == user_info_out_ok || this.current_status == user_info_recahrge) { + this.userInfoLayout.setVisibility(View.VISIBLE); + } else { + this.userInfoLayout.setVisibility(View.GONE); + } + } + + public void configView() { +// String avator = "http://img5.duitang.com/uploads/item/201409/26/20140926190238_sdZHL.thumb.700_0.jpeg"; +// Glide.with(this).load(avator).into(this.avator_imageview); // 暂时没有网络 + this.setCurrentStatus(welcome_show); + + + eggClickUtil = new EggClickUtil(new EggClickUtil.onEggClickListener() { + @Override + public void onClickAction() { + Intent intent = new Intent(MainActivity.this, SDSettingActivity.class); + startActivity(intent); + } + }); + } + + /** + * 加载人脸识别信息 + */ + @Subscribe(threadMode = ThreadMode.MAIN) + public void loadFaceidInfo(FaceidEvent faceidEvent) { + if (faceidEvent.isDebug){ + // 这里检测到 debug模式下,显示toast + showToast(faceidEvent.msg); + return; + } + + MemberDto memberDto = faceidEvent.getMember(); + if (memberDto != null){ + // 这个是会员进入现场 + if (errorDialog != null){ + if (errorDialog.isShow){ + errorDialog.dismiss(); + } + } + CrashReport.postCatchedException(new Throwable("接受到命令 " + memberDto.getCode())); + + + // 监听到头像 + Glide.with(this).load(memberDto.getAvatar()).into(this.avator_imageview); + String message = memberDto.getMessage(); + user_name_label.setText(memberDto.getName()); + user_phone_label.setText(memberDto.getMobile()); + if (memberDto.getAmount()!= null){ + user_amount_label.setText(memberDto.getAmount().toString()); + } + if (memberDto.getPlacePrice() != null){ + unit_price_label.setText(memberDto.getPlacePrice().toString()); + } +// welcome_label.setText(String.format("欢迎%s进场", memberDto.getName())); + welcome_label.setText(message); + if (TextUtils.isEmpty(memberDto.getCardName())) { + memberInfoLineView.setVisibility(View.GONE); + memberInfopackLayout.setVisibility(View.GONE); // 场地的信息 + } else { + memberInfoLineView.setVisibility(View.VISIBLE); + memberInfopackLayout.setVisibility(View.VISIBLE); + this.user_place_label.setText(memberDto.getCardName()); + } + + if (memberDto.getCode() == 2){ + // 出场成功 + startCountDownTime(user_info_out_ok); + }else if (memberDto.getCode() == 1){ + // 入场成功 + if (memberDto.isFirst()){ + // 每天的第一次 + firstEnterHome(); + }else{ + startCountDownTime(user_info_ok); + } + + }else if (memberDto.getCode() == 0 ){ + // 入场失败 + startCountDownTime(user_info_fail); + }else if (memberDto.getCode() == -1){ + // 余额不足 + startCountDownTime(user_info_recahrge); + } + }else { + // 这个是非会员进入现场 + this.showStrangerDialog(); + } + + } + + @Override + protected void onStop() { + super.onStop(); + + mMediaPlayer.stop(); + + mMediaPlayer.getVLCVout().detachViews(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (EventBus.getDefault().isRegistered(this)) { + EventBus.getDefault().unregister(this); + } + } + + /** + * 更新视频窗口 + */ + private void updateVideoSurfaces() { + int sw = getWindow().getDecorView().getWidth(); + int sh = getWindow().getDecorView().getHeight(); + + // sanity check + if (sw * sh == 0) { + Log.e(TAG, "Invalid surface size"); + return; + } + + + Log.d("sander", "size : " + sw + " : " + sh); + + // 目前不清楚这里布局的条件,这个慢慢调出来的 + mMediaPlayer.getVLCVout().setWindowSize(1400, 800); + + ViewGroup.LayoutParams lp = faceid_video_view.getLayoutParams(); + if (true) { + /* Case of OpenGL vouts: handles the placement of the video using MediaPlayer API */ + lp.width = sw; + lp.height = sh; + faceid_video_view.setLayoutParams(lp); + mMediaPlayer.setAspectRatio(null); + mMediaPlayer.setScale(0); + return; + } + + if (lp.width == lp.height && lp.width == ViewGroup.LayoutParams.MATCH_PARENT) { + /* We handle the placement of the video using Android View LayoutParams */ + mMediaPlayer.setAspectRatio(null); + mMediaPlayer.setScale(0); + } + + double dw = sw, dh = sh; + final boolean isPortrait = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; + + if (sw > sh && isPortrait || sw < sh && !isPortrait) { + dw = sh; + dh = sw; + } + + // compute the aspect ratio + double ar, vw; + if (mVideoSarDen == mVideoSarNum) { + /* No indication about the density, assuming 1:1 */ + vw = mVideoVisibleWidth; + ar = (double) mVideoVisibleWidth / (double) mVideoVisibleHeight; + } else { + /* Use the specified aspect ratio */ + vw = mVideoVisibleWidth * (double) mVideoSarNum / mVideoSarDen; + ar = vw / mVideoVisibleHeight; + } + + // compute the display aspect ratio + double dar = dw / dh; + + switch (CURRENT_SIZE) { + case SURFACE_BEST_FIT: + if (dar < ar) + dh = dw / ar; + else + dw = dh * ar; + break; + case SURFACE_FIT_SCREEN: + if (dar >= ar) + dh = dw / ar; /* horizontal */ + else + dw = dh * ar; /* vertical */ + break; + case SURFACE_FILL: + break; + case SURFACE_16_9: + ar = 16.0 / 9.0; + if (dar < ar) + dh = dw / ar; + else + dw = dh * ar; + break; + case SURFACE_4_3: + ar = 4.0 / 3.0; + if (dar < ar) + dh = dw / ar; + else + dw = dh * ar; + break; + case SURFACE_ORIGINAL: + dh = mVideoVisibleHeight; + dw = vw; + break; + } + + // set display size + lp.width = (int) Math.ceil(dw * mVideoWidth / mVideoVisibleWidth); + lp.height = (int) Math.ceil(dh * mVideoHeight / mVideoVisibleHeight); + faceid_video_view.setLayoutParams(lp); + faceid_video_view.invalidate(); + } + + @Override + public void onNewVideoLayout(IVLCVout vlcVout, int width, int height, int visibleWidth, int visibleHeight, int sarNum, int sarDen) { + mVideoWidth = width; + mVideoHeight = height; + mVideoVisibleWidth = visibleWidth; + mVideoVisibleHeight = visibleHeight; + mVideoSarNum = sarNum; + mVideoSarDen = sarDen; + updateVideoSurfaces(); + } + + public void firstEnterHome(){ + if (this.firstCountDownTimer != null){ + this.firstCountDownTimer.cancel(); + this.firstCountDownTimer = null; + } + topInfoTextView.setText("人脸认证通过"); + // 欢迎页面 + this.welcome_layout.setVisibility(View.GONE); + // 顶部的 文字 + this.welcome_label.setVisibility(View.VISIBLE); + // 用户信息 layout + this.userInfoLayout.setVisibility(View.VISIBLE); + // 用户信息中的 价格layout + this.unit_price_layout.setVisibility(View.VISIBLE); + this.unit_price_line_view.setVisibility(View.VISIBLE); + this.firstCountDownTimer = new CountDownTimer(3 * 1000, 1 * 1000) { + @Override + public void onTick(long l) { + + } + + @Override + public void onFinish() { + firstCountDownTimer.cancel(); + firstCountDownTimer = null; + startCountDownTime(user_info_ok); + } + }; + + this.firstCountDownTimer.start(); + } + + public void startCountDownTime(final int current_status) { + + if (this.countDownTimer != null) { + stopCountDownTime(); + + } + if (this.firstCountDownTimer != null){ + firstCountDownTimer.cancel(); + firstCountDownTimer = null; + } + topInfoTextView.setVisibility(View.VISIBLE); + count_down_label.setVisibility(View.GONE); + if (current_status == user_info_ok) { + this.setMaxCountDownTime(maxTime); + topInfoTextView.setVisibility(View.GONE); + } else if (current_status == user_info_recahrge){ + topInfoTextView.setText("当前余额不足,请立即充值!"); + } else if (current_status == user_info_out_ok){ + topInfoTextView.setText("欢迎下次光临"); + }else if (current_status == user_info_fail){ + topInfoTextView.setText("入场失败"); + } + + this.setCurrentStatus(current_status); + + this.countDownTimer = new CountDownTimer(maxTime * 1000, 1 * 1000) { + @Override + public void onTick(long l) { + if (current_status == user_info_ok) { + topInfoTextView.setVisibility(View.GONE); + setMaxCountDownTime(maxCountDownTime - 1); + } else if (current_status == user_info_recahrge){ + topInfoTextView.setText("当前余额不足,请立即充值!"); + }else { + + } + } + + @Override + public void onFinish() { + setCurrentStatus(welcome_show); + stopCountDownTime(); + } + }; + + this.countDownTimer.start(); + } + + public void stopCountDownTime() { + this.countDownTimer.cancel(); + this.countDownTimer = null; + } + + public void showStrangerDialog(){ + if (errorDialog == null){ + errorDialog = new SDErrorDialog(this); + } + errorDialog.showDialog(); + } + + + @OnClick({R.id.gust_info_view}) void onClick(View view){ + if (view.getId() == R.id.gust_info_view){ + eggClickUtil.checkoutHideFunction(); + } + } +} diff --git a/app/src/main/java/com/ydd/sportfaceid/SDErrorDialog.java b/app/src/main/java/com/ydd/sportfaceid/SDErrorDialog.java new file mode 100644 index 0000000..116ef46 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/SDErrorDialog.java @@ -0,0 +1,94 @@ +package com.ydd.sportfaceid; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.os.CountDownTimer; +import android.support.annotation.NonNull; +import android.view.View; + +import butterknife.OnClick; + +public class SDErrorDialog extends Dialog { + + private Context mContent; + + public boolean isShow; + + private CountDownTimer countDownTimer; + public SDErrorDialog(Context context) { + super(context,R.style.Dialog_Fullscreen); + this.mContent = context; + + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_error_layout); + + } + + private void stopCountDown(){ + if (this.countDownTimer != null){ + this.countDownTimer.cancel(); + this.countDownTimer = null; + } + } + private void startCountDown(){ + if (this.countDownTimer != null){ + this.countDownTimer.cancel(); + this.countDownTimer = null; + } + + this.countDownTimer = new CountDownTimer(5000, 1000) { + @Override + public void onTick(long l) { + + } + + @Override + public void onFinish() { + dismiss(); + } + }; + this.countDownTimer.start(); + } + + @Override + public void show() { + super.show(); + this.isShow = true; + this.startCountDown(); + } + + @Override + public void dismiss() { + super.dismiss(); + this.isShow = false; + } + + public void showDialog(){ + if (this.isShow){ + this.startCountDown(); + }else { + this.show(); + } + } +// public void dismissDialog(){ +// try{ +// if (this.isShow){ +// this.dismiss(); +// } +// }catch (Exception ex){ +// ex.printStackTrace(); +// } +// +// } + + + @OnClick({R.id.dialog_view}) void onClick(View view){ + this.dismiss(); + + } +} diff --git a/app/src/main/java/com/ydd/sportfaceid/StartApplication.java b/app/src/main/java/com/ydd/sportfaceid/StartApplication.java new file mode 100644 index 0000000..2024ec2 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/StartApplication.java @@ -0,0 +1,38 @@ +package com.ydd.sportfaceid; + +import android.app.Application; + +import com.tencent.bugly.Bugly; +import com.ydd.sportfaceid.config.SDAppConfig; + +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + + +/** + * StartApplication.java + * + * @author peakren + * @date 2018/6/27 5:02 PM + */ + +public class StartApplication extends Application { + + static private StartApplication sInstance; + + static public StartApplication getAppContext() { + return sInstance; + } + + public static Executor executor = Executors.newCachedThreadPool(); + + @Override + public void onCreate() { + super.onCreate(); + sInstance = this; + SDAppConfig.getInstance().init(this); + Bugly.init(getApplicationContext(), "264ca5c997", false); + } + +} diff --git a/app/src/main/java/com/ydd/sportfaceid/config/GlobalConfig.java b/app/src/main/java/com/ydd/sportfaceid/config/GlobalConfig.java new file mode 100644 index 0000000..fe8e954 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/config/GlobalConfig.java @@ -0,0 +1,22 @@ +package com.ydd.sportfaceid.config; + + +/** + * 全局配置常量 + * + * @author peakren + * @date 05/12/2017 10:29 PM + */ + +public class GlobalConfig { + + public static boolean isConnected = false; + + + /** + * face++的websocket连接状态 + */ + public static boolean FACE_WS_CONNECTED = false; + + +} diff --git a/app/src/main/java/com/ydd/sportfaceid/config/SDAppConfig.java b/app/src/main/java/com/ydd/sportfaceid/config/SDAppConfig.java new file mode 100644 index 0000000..1cbda21 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/config/SDAppConfig.java @@ -0,0 +1,124 @@ +package com.ydd.sportfaceid.config; + +import android.content.Context; +import android.content.SharedPreferences; +import android.text.TextUtils; +import android.util.Log; + +import org.w3c.dom.Text; + +public class SDAppConfig { + + public final static String TAG = "sanderConfig"; + + public static SDAppConfig config = null; + + public static String Key_sace_cache = "save_cache"; + + public static String camera_rstp_first = "rtsp://192.168.1.161/user=admin&password=&channel=1&stream=0.sdp?"; + public static String camera_rstp_sconde = "rtsp://192.168.1.160:8554/0/0/0"; + + + public String camera_local_rstp_first; + public final static String key_camera_local_rstp_first = "key_camera_local_rstp_first"; + + public String camera_local_rstp_last; + public final static String key_camera_local_rstp_last = "key_camera_local_rstp_last"; + + + private Context mContext; + + private SharedPreferences sp; + private SharedPreferences.Editor sp_editor; + + public int getCurrent_selected_camera() { + if (this.current_selected_camera >= 0 ){ + this.current_selected_camera = sp.getInt(key_current_selectd_camera,-1); + } + return current_selected_camera; + } + + public void setCurrent_selected_camera(int current_selected_camera) { + this.current_selected_camera = current_selected_camera; + sp_editor.putInt(key_current_selectd_camera, current_selected_camera); + sp_editor.commit(); + } + + private final static String key_current_selectd_camera = "key_current_selectd_camera"; + private int current_selected_camera = -1; + public static SDAppConfig getInstance(){ + synchronized (SDAppConfig.class){ + if (config == null){ + config = new SDAppConfig(); + } + } + return config; + } + + public void init(Context context){ + this.mContext = context; + synchronized (SDAppConfig.class){ + if (sp == null){ + sp = this.mContext.getSharedPreferences(Key_sace_cache, Context.MODE_PRIVATE); + sp_editor = sp.edit(); + this.configData(); + }else { + Log.e(TAG, "这里只能被执行一次"); + } + } + } + public void configData(){ + this.camera_local_rstp_first = sp.getString(key_camera_local_rstp_first, ""); + if (TextUtils.isEmpty(this.camera_local_rstp_first)){ + this.setCamera_local_rstp_first(camera_rstp_first); + } + this.camera_local_rstp_last = sp.getString(key_camera_local_rstp_last, ""); + if (TextUtils.isEmpty(this.camera_local_rstp_last)){ + this.setCamera_local_rstp_last(camera_rstp_sconde); + } + this.current_selected_camera = sp.getInt(key_current_selectd_camera,-1); + if (this.current_selected_camera == -1){ + this.setCurrent_selected_camera(0); + } + + } + + + + public String getCamera_local_rstp_first() { + if (TextUtils.isEmpty(camera_local_rstp_first)){ + camera_local_rstp_first = sp.getString(key_camera_local_rstp_first, ""); + } + return camera_local_rstp_first; + } + + public void setCamera_local_rstp_first(String camera_local_rstp_first) { + this.camera_local_rstp_first = camera_local_rstp_first; + sp_editor.putString(key_camera_local_rstp_first, camera_local_rstp_first); + sp_editor.commit(); + } + + public String getCamera_local_rstp_last() { + if (TextUtils.isEmpty(camera_local_rstp_last)){ + camera_local_rstp_last = sp.getString(key_camera_local_rstp_last, ""); + } + return camera_local_rstp_last; + } + + public void setCamera_local_rstp_last(String camera_local_rstp_last) { + this.camera_local_rstp_last = camera_local_rstp_last; + sp_editor.putString(key_camera_local_rstp_last, camera_local_rstp_last); + sp_editor.commit(); + } + + public String getCurrentCameraUrl(){ + if (this.current_selected_camera == 1){ + return this.getCamera_local_rstp_last(); + } + return this.getCamera_local_rstp_first(); + } + + + + +} diff --git a/app/src/main/java/com/ydd/sportfaceid/event/FaceidEvent.java b/app/src/main/java/com/ydd/sportfaceid/event/FaceidEvent.java new file mode 100644 index 0000000..fc2b810 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/event/FaceidEvent.java @@ -0,0 +1,30 @@ +package com.ydd.sportfaceid.event; + +import com.ydd.sportfaceid.net.dto.MemberDto; + +/** + * 消息事件 + * + * @author peakren + * @date 08/12/2017 11:16 PM + */ +public class FaceidEvent { + + private MemberDto member; + + public FaceidEvent(MemberDto member) { + this.member = member; + } + + public MemberDto getMember() { + return member; + } + + public void setMember(MemberDto member) { + this.member = member; + } + + public boolean isDebug; + + public String msg; +} diff --git a/app/src/main/java/com/ydd/sportfaceid/event/MessageEvent.java b/app/src/main/java/com/ydd/sportfaceid/event/MessageEvent.java new file mode 100644 index 0000000..393e0e2 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/event/MessageEvent.java @@ -0,0 +1,26 @@ +package com.ydd.sportfaceid.event; + +import com.ydd.sportfaceid.net.dto.MemberDto; + +/** + * 消息事件 + * + * @author peakren + * @date 08/12/2017 11:16 PM + */ +public class MessageEvent { + + private String message; + + public MessageEvent(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/app/src/main/java/com/ydd/sportfaceid/main/SDBaseActivity.java b/app/src/main/java/com/ydd/sportfaceid/main/SDBaseActivity.java new file mode 100644 index 0000000..a6d0046 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/main/SDBaseActivity.java @@ -0,0 +1,94 @@ +package com.ydd.sportfaceid.main; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.graphics.drawable.ColorDrawable; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.text.TextUtils; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Toast; + + +import butterknife.ButterKnife; + +/** + * Created by sandershan on 2018/11/27. + */ + +public class SDBaseActivity extends Activity { + private Toast mToast; + + @Override + public void setContentView(View view) { + super.setContentView(view); + ButterKnife.bind(this); + + } + + @Override + public void setContentView(int layoutResID) { + super.setContentView(layoutResID); + ButterKnife.bind(this); + + } + + @Override + public void setContentView(View view, ViewGroup.LayoutParams params) { + super.setContentView(view, params); + ButterKnife.bind(this); +// ScreenAdapterTools.getInstance().loadView(getWindow().getDecorView()); + + } + + @Override + protected void onDestroy() { + super.onDestroy(); + + } + + /** + * toast提示 + * + * @param msg 待提示内容 + */ + public void showToast(String msg) { + if (TextUtils.isEmpty(msg)) { + return; + } + if (mToast == null) { + mToast = Toast.makeText(this, msg, Toast.LENGTH_SHORT); + } else { + mToast.setText(msg); + } + mToast.show(); + } + /** + * 检测当的网络(WLAN、3G/2G)状态 + * @return true 表示网络可用 + */ + public boolean isNetworkAvailable() { + Context context = this; + ConnectivityManager connectivity = (ConnectivityManager) context + .getSystemService(Context.CONNECTIVITY_SERVICE); + if (connectivity != null) { + NetworkInfo info = connectivity.getActiveNetworkInfo(); + if (info != null && info.isConnected()) + { + // 当前网络是连接的 + if (info.getState() == NetworkInfo.State.CONNECTED) + { + // 当前所连接的网络可用 + return true; + } + } + } + showToast("当前网络不好,请检查网络"); + return false; + } + +} diff --git a/app/src/main/java/com/ydd/sportfaceid/net/ClientHandler.java b/app/src/main/java/com/ydd/sportfaceid/net/ClientHandler.java new file mode 100644 index 0000000..6a2a672 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/net/ClientHandler.java @@ -0,0 +1,111 @@ +package com.ydd.sportfaceid.net; + +import android.app.Activity; +import android.util.Log; +import android.widget.Toast; + +import com.ydd.sportfaceid.StartApplication; +import com.ydd.sportfaceid.config.GlobalConfig; +import com.ydd.sportfaceid.session.ClientTcpSession; +import com.ydd.sportfaceid.service.MessageService; +import com.ydd.sportfaceid.net.dto.HeartBeat; +import com.ydd.sportfaceid.net.dto.Message; +import com.ydd.sportfaceid.utils.AppUtil; +import com.ydd.sportfaceid.utils.DeviceIdUtil; +import com.ydd.sportfaceid.utils.JsonMapper; + +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.handler.timeout.IdleState; +import io.netty.handler.timeout.IdleStateEvent; + +/** + * 通讯服务器请求处理 + * + * @author peakren + * @date 05/12/2017 10:27 PM + */ +@ChannelHandler.Sharable +public class ClientHandler extends ChannelInboundHandlerAdapter { + + private final static String TAG = "ClientHandler"; + + private boolean hasRead = false; + + private Activity mContext; + + public ClientHandler(Activity context) { + mContext = context; + } + + @Override + public void channelRegistered(ChannelHandlerContext ctx) throws Exception { + super.channelRegistered(ctx); + ClientTcpSession.getInstance().setContext(ctx); + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + super.channelActive(ctx); + //服务器连上以后立即模拟心跳返回 + ctx.writeAndFlush(getHbMessage()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + super.channelInactive(ctx); + Log.e(TAG, "----close----"); + GlobalConfig.isConnected =false; + ClientThread.getInstance().clearFuture(); + ClientThread.getInstance().restart(); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + super.channelRead(ctx, msg); + Log.i(TAG, "----read data: " + msg.toString() + "----"); + Message message = JsonMapper.fromJson(msg.toString(), Message.class); + MessageService.getInstance().execute(message); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + super.exceptionCaught(ctx, cause); + Log.e(TAG, "----tcp exception----"); + GlobalConfig.isConnected = false; + ctx.close(); + } + + /** + * 获取心跳返回消息 + * + * @return + */ + private Message getHbMessage() { + HeartBeat hb = new HeartBeat(); + hb.setVersionCode(AppUtil.getVersionCode(StartApplication.getAppContext())); + Message message = new Message(); + message.setCmdId(Cmd.HB.id); +// message.setDeviceId(DeviceIdUtil.generateDeviceId(mContext)); + return message; + } + + /** + * 心跳处理 + * + * @param ctx + * @param evt + * @throws Exception + */ + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + if (IdleStateEvent.class.isAssignableFrom(evt.getClass())) { + IdleStateEvent event = (IdleStateEvent) evt; + if (event.state() == IdleState.ALL_IDLE) { + ctx.writeAndFlush(getHbMessage()); + } + } + } + +} diff --git a/app/src/main/java/com/ydd/sportfaceid/net/ClientInitializer.java b/app/src/main/java/com/ydd/sportfaceid/net/ClientInitializer.java new file mode 100644 index 0000000..3c6621e --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/net/ClientInitializer.java @@ -0,0 +1,42 @@ +package com.ydd.sportfaceid.net; + +import android.content.Context; + +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.LengthFieldBasedFrameDecoder; +import io.netty.handler.timeout.IdleStateHandler; + + +public class ClientInitializer extends ChannelInitializer { + + private Context mContext; + + private final static int TIME_HEART_BEAT = 20; + + public ClientThread.ReConnectHandler reConnectHandler; + public ClientHandler dmClientHandler; + + public ClientInitializer(ClientThread.ReConnectHandler handler) { + reConnectHandler = handler; + } + + public ClientInitializer(ClientThread.ReConnectHandler handler, ClientHandler dmClientHandler) { + reConnectHandler = handler; + this.dmClientHandler = dmClientHandler; + } + + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + ChannelPipeline pipeline = ch.pipeline(); + pipeline.addLast("reconnect", reConnectHandler); + pipeline.addLast("idleStateHandler", new IdleStateHandler(TIME_HEART_BEAT, TIME_HEART_BEAT, TIME_HEART_BEAT)); + pipeline.addLast(new MessageEncoder()); + pipeline.addFirst(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 4, 4, 0, 0)); + pipeline.addLast(new MessageDecoder()); + pipeline.addLast(dmClientHandler); + } + +} diff --git a/app/src/main/java/com/ydd/sportfaceid/net/ClientThread.java b/app/src/main/java/com/ydd/sportfaceid/net/ClientThread.java new file mode 100644 index 0000000..e4ea970 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/net/ClientThread.java @@ -0,0 +1,170 @@ +package com.ydd.sportfaceid.net; + +import android.app.Activity; +import android.os.Handler; +import android.util.Log; + +import com.ydd.sportfaceid.BuildConfig; +import com.ydd.sportfaceid.config.GlobalConfig; +import com.ydd.sportfaceid.event.MessageEvent; +import com.ydd.sportfaceid.utils.SharedPreferencesUtil; + +import org.greenrobot.eventbus.EventBus; + +import java.net.InetSocketAddress; +import java.util.concurrent.TimeUnit; + +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; + + +/** + * 客户端通讯 + * + * @author peakren + * @date 07/12/2017 10:12 PM + */ +public class ClientThread { + + private final static String TAG = "sander"; + + private static ClientThread instance; + + private volatile EventLoopGroup workerGroup; + private volatile Bootstrap bootstrap; + private volatile boolean closed = false; + private String remoteHost; + private int remotePort; + + private Activity mContext; + + private ChannelFuture future; + + + public static ClientThread getInstance() { + if (instance == null) { + synchronized (ClientThread.class) { + if (instance == null) { + instance = new ClientThread(BuildConfig.SERVER_IP, Integer.valueOf(BuildConfig.SERVER_PORT)); + } + } + } + return instance; + } + + public ClientThread(String remoteHost, int remotePort) { + this.remoteHost = remoteHost; + this.remotePort = remotePort; + } + + public void run() { + + closed = false; + workerGroup = new NioEventLoopGroup(); + bootstrap = new Bootstrap(); + bootstrap.group(workerGroup); + bootstrap.channel(NioSocketChannel.class); + bootstrap.option(ChannelOption.TCP_NODELAY, true); + bootstrap.option(ChannelOption.SO_KEEPALIVE, true); + + ReConnectHandler reConnectHandler = new ReConnectHandler(); + ClientHandler dmClientHandler = new ClientHandler(mContext); + ClientInitializer channelInitializer = new ClientInitializer(reConnectHandler, dmClientHandler); + + bootstrap.handler(channelInitializer); + doConnect(); + } + + public void clearFuture(){ + future = null; + } + + public void doConnect() { + Log.d("sander","现在开始链接了"); + if (closed) { + return; + } + remoteHost = SharedPreferencesUtil.getServerIp(); + remotePort = SharedPreferencesUtil.getServerPort(); + +// if (future != null){ +// return; +// } +// future = null; + if (GlobalConfig.isConnected){ + return; + } + + Log.d("sander", "连接 = " + remoteHost + " " + remotePort); + future = bootstrap.connect(new InetSocketAddress(remoteHost, remotePort)); + future.addListener(new ChannelFutureListener() { + public void operationComplete(ChannelFuture f) throws Exception { + f.channel().eventLoop().schedule(new Runnable() { + @Override + public void run() { + if (!f.isSuccess()) { + if (GlobalConfig.isConnected) { + GlobalConfig.isConnected = false; + } + doConnect(); + EventBus.getDefault().post(new MessageEvent("等待连接")); + Log.e(TAG, "连接失败!"); + } else { + EventBus.getDefault().post(new MessageEvent("已连接")); + Log.i(TAG, "连接成功!"); + GlobalConfig.isConnected = true; + } + } + }, 2, TimeUnit.SECONDS); + + + } + }); + + } + + + public void setContext(Activity context) { + mContext = context; + } + + + public void close() { + closed = true; + workerGroup.shutdownGracefully(); + } + + public void restart() { + this.remoteHost = SharedPreferencesUtil.getServerIp(); + this.remotePort = SharedPreferencesUtil.getServerPort(); + close(); + run(); + } + + @ChannelHandler.Sharable + public class ReConnectHandler extends ChannelInboundHandlerAdapter { + + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + super.channelInactive(ctx); + System.out.println("inactive"); + ctx.channel().eventLoop().schedule(new Runnable() { + @Override + public void run() { + doConnect(); + } + }, 1, TimeUnit.SECONDS); + } + } + + +} diff --git a/app/src/main/java/com/ydd/sportfaceid/net/Cmd.java b/app/src/main/java/com/ydd/sportfaceid/net/Cmd.java new file mode 100644 index 0000000..626118a --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/net/Cmd.java @@ -0,0 +1,45 @@ +package com.ydd.sportfaceid.net; + +/** + * 消息协议指令定义 + * + * @Author peakren + * @Date 08/12/2017 11:51 AM + */ +public enum Cmd { + + + HB("hb", "心跳"), + + FACEID("faceid", "人脸识别"), + + FACEID_RESPONSE("faceid_response_upload", "识别结果"), + + RECEV_FACE_IMAGE("recev_face_image", "接收人脸照片"), + + RECEV_FACE_IMAGE_R("recev_face_image_r", "返回上传图片结果"), + + OPEN_DOOR("open_door", "开门禁"); + + + public String id; + + public String text; + + Cmd(String id, String text) { + this.id = id; + this.text = text; + + } + + public static Cmd getCmd(String id) { + for (Cmd cmd : Cmd.values()) { + if (cmd.id.equalsIgnoreCase(id)) { + return cmd; + } + } + return Cmd.HB; + } + +} + diff --git a/app/src/main/java/com/ydd/sportfaceid/net/CustomDecoder.java b/app/src/main/java/com/ydd/sportfaceid/net/CustomDecoder.java new file mode 100644 index 0000000..032f8cd --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/net/CustomDecoder.java @@ -0,0 +1,40 @@ +package com.ydd.sportfaceid.net; + +import java.nio.ByteOrder; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.LengthFieldBasedFrameDecoder; + + +/** + * 自定义解码器,解决粘包和分包问题 + * + * @author peakren + * @date 07/12/2017 10:03 PM + */ +public class CustomDecoder extends LengthFieldBasedFrameDecoder { + + public CustomDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength) { + super(maxFrameLength, lengthFieldOffset, lengthFieldLength); + } + + public CustomDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip) { + super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip); + } + + public CustomDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast) { + super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip, failFast); + } + + public CustomDecoder(ByteOrder byteOrder, int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast) { + super(byteOrder, maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip, failFast); + } + + + @Override + protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception { + return super.decode(ctx, in); + } + +} diff --git a/app/src/main/java/com/ydd/sportfaceid/net/DataConfig.java b/app/src/main/java/com/ydd/sportfaceid/net/DataConfig.java new file mode 100644 index 0000000..1b3c248 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/net/DataConfig.java @@ -0,0 +1,14 @@ +package com.ydd.sportfaceid.net; + +/** + * Created by hehelt on 16/2/26. + */ +public class DataConfig { + + public static final int MAGIC_WORD = 0x9DDD; + public static final int MAGIC_WORD_INDEX = 0; + public static final int LENGTH_INDEX = 4; + public static final int DATA_INDEX = 8; + + +} diff --git a/app/src/main/java/com/ydd/sportfaceid/net/DoorHandler.java b/app/src/main/java/com/ydd/sportfaceid/net/DoorHandler.java new file mode 100644 index 0000000..a4468e0 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/net/DoorHandler.java @@ -0,0 +1,14 @@ +package com.ydd.sportfaceid.net; + + +/** + * 门禁处理 + * DoorHandler.java + * + * @author peakren + * @date 2019/4/17 12:44 PM + */ +public class DoorHandler { + + +} diff --git a/app/src/main/java/com/ydd/sportfaceid/net/MessageDecoder.java b/app/src/main/java/com/ydd/sportfaceid/net/MessageDecoder.java new file mode 100644 index 0000000..f314018 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/net/MessageDecoder.java @@ -0,0 +1,48 @@ +package com.ydd.sportfaceid.net; + +import java.io.UnsupportedEncodingException; +import java.util.List; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + +/** + * Created by hehelt on 16/2/26. + *

+ * 解码器 + */ +public class MessageDecoder extends ByteToMessageDecoder { + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { + if (in.capacity() >= DataConfig.LENGTH_INDEX) { + int magicWord = in.readInt(); + if (magicWord == DataConfig.MAGIC_WORD) { + int length = in.readInt(); + byte[] msg = new byte[length]; + in.readBytes(msg); + String message = new String(msg, "utf-8"); + out.add(message); + } + } + } + + /** + * 解析从服务器接受的消息 + * + * @param buf + * @return + */ + private String getMessage(ByteBuf buf) { + + byte[] con = new byte[buf.readableBytes()]; + buf.readBytes(con); + try { + return new String(con, "utf-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/app/src/main/java/com/ydd/sportfaceid/net/MessageEncoder.java b/app/src/main/java/com/ydd/sportfaceid/net/MessageEncoder.java new file mode 100644 index 0000000..e6957fe --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/net/MessageEncoder.java @@ -0,0 +1,28 @@ +package com.ydd.sportfaceid.net; + +import android.util.Log; + +import com.ydd.sportfaceid.net.dto.Message; +import com.ydd.sportfaceid.utils.JsonMapper; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; + +/** + * 自定义编码器, 1个字节固定头+4个字节长度+内容 + */ +public class MessageEncoder extends MessageToByteEncoder { + + private String charset = "utf-8"; + private final static String TAG = "MessageEncoder"; + + @Override + protected void encode(ChannelHandlerContext ctx, Message message, ByteBuf out) throws Exception { + out.writeInt(DataConfig.MAGIC_WORD); + String msg = JsonMapper.toJson(message); + Log.i(TAG, "send data:" + msg); + out.writeInt(msg.getBytes(charset).length); + out.writeBytes(msg.getBytes(charset)); + } +} diff --git a/app/src/main/java/com/ydd/sportfaceid/net/dto/AddFaceResponse.java b/app/src/main/java/com/ydd/sportfaceid/net/dto/AddFaceResponse.java new file mode 100644 index 0000000..7360ec9 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/net/dto/AddFaceResponse.java @@ -0,0 +1,142 @@ +package com.ydd.sportfaceid.net.dto; + +import com.google.gson.annotations.Expose; + +public class AddFaceResponse { + + /** + * code : 0 + * data : {"company_id":1,"id":4,"origin_url":"/static/upload/origin/2018-08-09/v2_1ea4b7847d1ea56b773aec99441af52dcbf9ca7d.jpg","quality":0.992649,"subject_id":null,"url":"/static/upload/photo/2018-08-09/v2_fa9dcfd045ff5232aa446f5645cbb031eef7ac74.jpg","version":7} + * page : {} + */ + + @Expose + private int code; + + @Expose + private DataBean data; + + @Expose + private PageBean page; + + @Expose + private String desc; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public DataBean getData() { + return data; + } + + public void setData(DataBean data) { + this.data = data; + } + + public PageBean getPage() { + return page; + } + + public void setPage(PageBean page) { + this.page = page; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public static class DataBean { + /** + * company_id : 1 + * id : 4 + * origin_url : /static/upload/origin/2018-08-09/v2_1ea4b7847d1ea56b773aec99441af52dcbf9ca7d.jpg + * quality : 0.992649 + * subject_id : null + * url : /static/upload/photo/2018-08-09/v2_fa9dcfd045ff5232aa446f5645cbb031eef7ac74.jpg + * version : 7 + */ + + @Expose + private int company_id; + @Expose + private int id; + @Expose + private String origin_url; + @Expose + private double quality; + @Expose + private Object subject_id; + @Expose + private String url; + @Expose + private int version; + + public int getCompany_id() { + return company_id; + } + + public void setCompany_id(int company_id) { + this.company_id = company_id; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getOrigin_url() { + return origin_url; + } + + public void setOrigin_url(String origin_url) { + this.origin_url = origin_url; + } + + public double getQuality() { + return quality; + } + + public void setQuality(double quality) { + this.quality = quality; + } + + public Object getSubject_id() { + return subject_id; + } + + public void setSubject_id(Object subject_id) { + this.subject_id = subject_id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public int getVersion() { + return version; + } + + public void setVersion(int version) { + this.version = version; + } + } + + public static class PageBean { + } +} diff --git a/app/src/main/java/com/ydd/sportfaceid/net/dto/BaseDto.java b/app/src/main/java/com/ydd/sportfaceid/net/dto/BaseDto.java new file mode 100644 index 0000000..41819c7 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/net/dto/BaseDto.java @@ -0,0 +1,86 @@ +package com.ydd.sportfaceid.net.dto; + +import com.google.gson.annotations.Expose; + +import java.io.Serializable; + +/** + * Created by peakren on 19/01/2018. + */ + +public class BaseDto implements Serializable { + + private static final long serialVersionUID = 3139438146199448677L; + + @Expose + private String cmdId; //指令 + + @Expose + private String deviceId; //设备ID + + /** + * 客户端IP + */ + @Expose + private String clientIp; + + /** + * 状态码 0正常 1错误 + */ + @Expose + private int errorCode = 0; + + /** + * 错误返回信息 + */ + @Expose + private String errorMsg; + + + public String getCmdId() { + return cmdId; + } + + public void setCmdId(String cmdId) { + this.cmdId = cmdId; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + /** + * 客户端IP,获取的内网IP + * + * @return + */ + public String getClientIp() { + return clientIp; + } + + public void setClientIp(String clientIp) { + this.clientIp = clientIp; + } + + public int getErrorCode() { + return errorCode; + } + + public void setErrorCode(int errorCode) { + this.errorCode = errorCode; + } + + public String getErrorMsg() { + return errorMsg; + } + + public void setErrorMsg(String errorMsg) { + this.errorMsg = errorMsg; + } + + +} diff --git a/app/src/main/java/com/ydd/sportfaceid/net/dto/FaceImageDto.java b/app/src/main/java/com/ydd/sportfaceid/net/dto/FaceImageDto.java new file mode 100644 index 0000000..c109214 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/net/dto/FaceImageDto.java @@ -0,0 +1,53 @@ +package com.ydd.sportfaceid.net.dto; + +import com.google.gson.annotations.Expose; + +import java.io.Serializable; +import java.math.BigDecimal; + + +/** + * 会员基本信息 + * MemberDto.java + * + * @author peakren + * @date 2018/12/20 8:39 PM + */ +public class FaceImageDto implements Serializable { + + + @Expose + private Integer faceId; + + @Expose + private Integer memberId; + + + @Expose + private String faceImage; + + + public Integer getFaceId() { + return faceId; + } + + public void setFaceId(Integer faceId) { + this.faceId = faceId; + } + + public Integer getMemberId() { + return memberId; + } + + public void setMemberId(Integer memberId) { + this.memberId = memberId; + } + + public String getFaceImage() { + return faceImage; + } + + public void setFaceImage(String faceImage) { + this.faceImage = faceImage; + } +} diff --git a/app/src/main/java/com/ydd/sportfaceid/net/dto/FaceRecognizeResponse.java b/app/src/main/java/com/ydd/sportfaceid/net/dto/FaceRecognizeResponse.java new file mode 100644 index 0000000..6d186ad --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/net/dto/FaceRecognizeResponse.java @@ -0,0 +1,639 @@ +package com.ydd.sportfaceid.net.dto; + +import java.io.Serializable; +import java.util.List; + +public class FaceRecognizeResponse implements Serializable { + + /** + * data : {"status":"recognized","track":6,"timestamp":1533808724,"face":{"image":"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","rect":{"top":918,"right":872,"bottom":990,"left":798}},"person":{"feature_id":0,"confidence":78.397995,"tag":"{\"description\": \"\", \"remark\": \"\", \"subject_type\": 0, \"name\": \"ndy\", \"inviter_id\": null, \"start_time\": 0, \"title\": \"\", \"interviewee\": \"\", \"avatar\": \"/static/upload/photo/2018-08-09/v2_cec2cd5140b55db4051d9c69775ec6ebaea5947b.jpg\", \"origin_photo_id\": 3, \"birthday\": null, \"id\": 5, \"entry_date\": null, \"department\": \"\", \"interviewee_pinyin\": \"\", \"job_number\": \"\", \"end_time\": 0}","id":"5"},"quality":0.9968518905807287} + * screen : {"camera_address":"rtsp://192.168.1.160:8554/0/0/0","allowed_subject_ids":[],"network_switcher_status":null,"box_token":"95a0f5b6-924d-4323-9296-39d258f2b3f9","description":null,"allow_all_subjects":true,"box_heartbeat":1533806262,"network_switcher":"","camera_name":"","camera_status":0,"allow_visitor":true,"screen_token":"3c566c3f-6d7f-437a-af56-8ba4a7852745","network_switcher_token":null,"box_status":"0","network_switcher_drive":0,"type":1,"id":1,"camera_position":"测试","box_address":"192.168.1.50"} + * person : {"src":"data:image/jpeg;base64,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","remark":"","subject_type":0,"description":"","inviter_id":null,"timestamp":1533808724,"start_time":0,"title":"","interviewee":"","job_number":"","entry_date":null,"origin_photo_id":3,"birthday":null,"avatar":"/static/upload/photo/2018-08-09/v2_cec2cd5140b55db4051d9c69775ec6ebaea5947b.jpg","department":"","end_time":0,"interviewee_pinyin":"","id":5,"name":"ndy"} + * error : 允许进入 + * open_door : true + * type : recognized + */ + + private DataBean data; + private ScreenBean screen; + private PersonBeanX person; + private String error; + private boolean open_door; + private String type; + + public DataBean getData() { + return data; + } + + public void setData(DataBean data) { + this.data = data; + } + + public ScreenBean getScreen() { + return screen; + } + + public void setScreen(ScreenBean screen) { + this.screen = screen; + } + + public PersonBeanX getPerson() { + return person; + } + + public void setPerson(PersonBeanX person) { + this.person = person; + } + + public String getError() { + return error; + } + + public void setError(String error) { + this.error = error; + } + + public boolean isOpen_door() { + return open_door; + } + + public void setOpen_door(boolean open_door) { + this.open_door = open_door; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public static class DataBean { + /** + * status : recognized + * track : 6 + * timestamp : 1533808724 + * face : {"image":"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","rect":{"top":918,"right":872,"bottom":990,"left":798}} + * person : {"feature_id":0,"confidence":78.397995,"tag":"{\"description\": \"\", \"remark\": \"\", \"subject_type\": 0, \"name\": \"ndy\", \"inviter_id\": null, \"start_time\": 0, \"title\": \"\", \"interviewee\": \"\", \"avatar\": \"/static/upload/photo/2018-08-09/v2_cec2cd5140b55db4051d9c69775ec6ebaea5947b.jpg\", \"origin_photo_id\": 3, \"birthday\": null, \"id\": 5, \"entry_date\": null, \"department\": \"\", \"interviewee_pinyin\": \"\", \"job_number\": \"\", \"end_time\": 0}","id":"5"} + * quality : 0.9968518905807287 + */ + + private String status; + private int track; + private FaceBean face; + private PersonBean person; + private double quality; + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public int getTrack() { + return track; + } + + public void setTrack(int track) { + this.track = track; + } + + + public FaceBean getFace() { + return face; + } + + public void setFace(FaceBean face) { + this.face = face; + } + + public PersonBean getPerson() { + return person; + } + + public void setPerson(PersonBean person) { + this.person = person; + } + + public double getQuality() { + return quality; + } + + public void setQuality(double quality) { + this.quality = quality; + } + + public static class FaceBean { + /** + * image : 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 + * rect : {"top":918,"right":872,"bottom":990,"left":798} + */ + + private String image; + private RectBean rect; + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } + + public RectBean getRect() { + return rect; + } + + public void setRect(RectBean rect) { + this.rect = rect; + } + + public static class RectBean { + /** + * top : 918 + * right : 872 + * bottom : 990 + * left : 798 + */ + + private int top; + private int right; + private int bottom; + private int left; + + public int getTop() { + return top; + } + + public void setTop(int top) { + this.top = top; + } + + public int getRight() { + return right; + } + + public void setRight(int right) { + this.right = right; + } + + public int getBottom() { + return bottom; + } + + public void setBottom(int bottom) { + this.bottom = bottom; + } + + public int getLeft() { + return left; + } + + public void setLeft(int left) { + this.left = left; + } + } + } + + public static class PersonBean { + /** + * feature_id : 0 + * confidence : 78.397995 + * tag : {"description": "", "remark": "", "subject_type": 0, "name": "ndy", "inviter_id": null, "start_time": 0, "title": "", "interviewee": "", "avatar": "/static/upload/photo/2018-08-09/v2_cec2cd5140b55db4051d9c69775ec6ebaea5947b.jpg", "origin_photo_id": 3, "birthday": null, "id": 5, "entry_date": null, "department": "", "interviewee_pinyin": "", "job_number": "", "end_time": 0} + * id : 5 + */ + + private int feature_id; + private double confidence; + private String tag; + private String id; + + public int getFeature_id() { + return feature_id; + } + + public void setFeature_id(int feature_id) { + this.feature_id = feature_id; + } + + public double getConfidence() { + return confidence; + } + + public void setConfidence(double confidence) { + this.confidence = confidence; + } + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + } + } + + public static class ScreenBean { + /** + * camera_address : rtsp://192.168.1.160:8554/0/0/0 + * allowed_subject_ids : [] + * network_switcher_status : null + * box_token : 95a0f5b6-924d-4323-9296-39d258f2b3f9 + * description : null + * allow_all_subjects : true + * box_heartbeat : 1533806262 + * network_switcher : + * camera_name : + * camera_status : 0 + * allow_visitor : true + * screen_token : 3c566c3f-6d7f-437a-af56-8ba4a7852745 + * network_switcher_token : null + * box_status : 0 + * network_switcher_drive : 0 + * type : 1 + * id : 1 + * camera_position : 测试 + * box_address : 192.168.1.50 + */ + + private String camera_address; + private Object network_switcher_status; + private String box_token; + private Object description; + private boolean allow_all_subjects; + private int box_heartbeat; + private String network_switcher; + private String camera_name; + private int camera_status; + private boolean allow_visitor; + private String screen_token; + private Object network_switcher_token; + private String box_status; + private int network_switcher_drive; + private int type; + private int id; + private String camera_position; + private String box_address; + private List allowed_subject_ids; + + public String getCamera_address() { + return camera_address; + } + + public void setCamera_address(String camera_address) { + this.camera_address = camera_address; + } + + public Object getNetwork_switcher_status() { + return network_switcher_status; + } + + public void setNetwork_switcher_status(Object network_switcher_status) { + this.network_switcher_status = network_switcher_status; + } + + public String getBox_token() { + return box_token; + } + + public void setBox_token(String box_token) { + this.box_token = box_token; + } + + public Object getDescription() { + return description; + } + + public void setDescription(Object description) { + this.description = description; + } + + public boolean isAllow_all_subjects() { + return allow_all_subjects; + } + + public void setAllow_all_subjects(boolean allow_all_subjects) { + this.allow_all_subjects = allow_all_subjects; + } + + public int getBox_heartbeat() { + return box_heartbeat; + } + + public void setBox_heartbeat(int box_heartbeat) { + this.box_heartbeat = box_heartbeat; + } + + public String getNetwork_switcher() { + return network_switcher; + } + + public void setNetwork_switcher(String network_switcher) { + this.network_switcher = network_switcher; + } + + public String getCamera_name() { + return camera_name; + } + + public void setCamera_name(String camera_name) { + this.camera_name = camera_name; + } + + public int getCamera_status() { + return camera_status; + } + + public void setCamera_status(int camera_status) { + this.camera_status = camera_status; + } + + public boolean isAllow_visitor() { + return allow_visitor; + } + + public void setAllow_visitor(boolean allow_visitor) { + this.allow_visitor = allow_visitor; + } + + public String getScreen_token() { + return screen_token; + } + + public void setScreen_token(String screen_token) { + this.screen_token = screen_token; + } + + public Object getNetwork_switcher_token() { + return network_switcher_token; + } + + public void setNetwork_switcher_token(Object network_switcher_token) { + this.network_switcher_token = network_switcher_token; + } + + public String getBox_status() { + return box_status; + } + + public void setBox_status(String box_status) { + this.box_status = box_status; + } + + public int getNetwork_switcher_drive() { + return network_switcher_drive; + } + + public void setNetwork_switcher_drive(int network_switcher_drive) { + this.network_switcher_drive = network_switcher_drive; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getCamera_position() { + return camera_position; + } + + public void setCamera_position(String camera_position) { + this.camera_position = camera_position; + } + + public String getBox_address() { + return box_address; + } + + public void setBox_address(String box_address) { + this.box_address = box_address; + } + + public List getAllowed_subject_ids() { + return allowed_subject_ids; + } + + public void setAllowed_subject_ids(List allowed_subject_ids) { + this.allowed_subject_ids = allowed_subject_ids; + } + } + + public static class PersonBeanX { + /** + * src : data:image/jpeg;base64,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 + * remark : + * subject_type : 0 + * description : + * inviter_id : null + * timestamp : 1533808724 + * start_time : 0 + * title : + * interviewee : + * job_number : + * entry_date : null + * origin_photo_id : 3 + * birthday : null + * avatar : /static/upload/photo/2018-08-09/v2_cec2cd5140b55db4051d9c69775ec6ebaea5947b.jpg + * department : + * end_time : 0 + * interviewee_pinyin : + * id : 5 + * name : ndy + */ + + private String src; + private String remark; + private int subject_type; + private String description; + private Object inviter_id; + private int timestamp; + private int start_time; + private String title; + private String interviewee; + private String job_number; + private Object entry_date; + private int origin_photo_id; + private Object birthday; + private String avatar; + private String department; + private int end_time; + private String interviewee_pinyin; + private int id; + private String name; + + public String getSrc() { + return src; + } + + public void setSrc(String src) { + this.src = src; + } + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } + + public int getSubject_type() { + return subject_type; + } + + public void setSubject_type(int subject_type) { + this.subject_type = subject_type; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Object getInviter_id() { + return inviter_id; + } + + public void setInviter_id(Object inviter_id) { + this.inviter_id = inviter_id; + } + + public int getTimestamp() { + return timestamp; + } + + public void setTimestamp(int timestamp) { + this.timestamp = timestamp; + } + + public int getStart_time() { + return start_time; + } + + public void setStart_time(int start_time) { + this.start_time = start_time; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getInterviewee() { + return interviewee; + } + + public void setInterviewee(String interviewee) { + this.interviewee = interviewee; + } + + public String getJob_number() { + return job_number; + } + + public void setJob_number(String job_number) { + this.job_number = job_number; + } + + public Object getEntry_date() { + return entry_date; + } + + public void setEntry_date(Object entry_date) { + this.entry_date = entry_date; + } + + public int getOrigin_photo_id() { + return origin_photo_id; + } + + public void setOrigin_photo_id(int origin_photo_id) { + this.origin_photo_id = origin_photo_id; + } + + public Object getBirthday() { + return birthday; + } + + public void setBirthday(Object birthday) { + this.birthday = birthday; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getDepartment() { + return department; + } + + public void setDepartment(String department) { + this.department = department; + } + + public int getEnd_time() { + return end_time; + } + + public void setEnd_time(int end_time) { + this.end_time = end_time; + } + + public String getInterviewee_pinyin() { + return interviewee_pinyin; + } + + public void setInterviewee_pinyin(String interviewee_pinyin) { + this.interviewee_pinyin = interviewee_pinyin; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } +} diff --git a/app/src/main/java/com/ydd/sportfaceid/net/dto/HeartBeat.java b/app/src/main/java/com/ydd/sportfaceid/net/dto/HeartBeat.java new file mode 100644 index 0000000..c46b6f4 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/net/dto/HeartBeat.java @@ -0,0 +1,44 @@ +package com.ydd.sportfaceid.net.dto; + + +import com.google.gson.annotations.Expose; + +import java.io.Serializable; + +/** + * 客户端心跳数据包 + * HeartBeat.java + * + * @author peakren + * @date 07/12/2017 10:23 PM + */ +public class HeartBeat implements Serializable { + + @Expose + private String versionCode; //客户端版本号 + + @Expose + private String apkUrl; //升级的软件下载地址 + + + public String getVersionCode() { + return versionCode; + } + + /** + * 客户端版本号 + * + * @param versionCode + */ + public void setVersionCode(String versionCode) { + this.versionCode = versionCode; + } + + public String getApkUrl() { + return apkUrl; + } + + public void setApkUrl(String apkUrl) { + this.apkUrl = apkUrl; + } +} diff --git a/app/src/main/java/com/ydd/sportfaceid/net/dto/MemberDto.java b/app/src/main/java/com/ydd/sportfaceid/net/dto/MemberDto.java new file mode 100644 index 0000000..9fa3d1b --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/net/dto/MemberDto.java @@ -0,0 +1,148 @@ +package com.ydd.sportfaceid.net.dto; + +import com.google.gson.annotations.Expose; + +import java.io.Serializable; +import java.math.BigDecimal; + + +/** + * 会员基本信息 + * MemberDto.java + * + * @author peakren + * @date 2018/12/20 8:39 PM + */ +public class MemberDto implements Serializable { + + /** + * 头像 + */ + @Expose + private String avatar; + + /** + * 姓名 + */ + @Expose + private String name; + + /** + * 手机号码 + */ + @Expose + private String mobile; + + /** + * 余额 + */ + @Expose + private BigDecimal amount; + + /** + * 场地名称 + */ + @Expose + private String placeName; + + /** + * 会员卡名称 + */ + @Expose + private String cardName; + + @Expose + private String message; + + /** + * 1成功进场 0不允许进场 + */ + @Expose + private int code; + + @Expose + private BigDecimal placePrice; + + @Expose + private boolean first; + + public BigDecimal getPlacePrice() { + return placePrice; + } + + public void setPlacePrice(BigDecimal placePrice) { + this.placePrice = placePrice; + } + + public boolean isFirst() { + return first; + } + + public void setFirst(boolean first) { + this.first = first; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public BigDecimal getAmount() { + return amount; + } + + public void setAmount(BigDecimal amount) { + this.amount = amount; + } + + public String getPlaceName() { + return placeName; + } + + public void setPlaceName(String placeName) { + this.placeName = placeName; + } + + public String getCardName() { + return cardName; + } + + public void setCardName(String cardName) { + this.cardName = cardName; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } +} diff --git a/app/src/main/java/com/ydd/sportfaceid/net/dto/Message.java b/app/src/main/java/com/ydd/sportfaceid/net/dto/Message.java new file mode 100644 index 0000000..402913d --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/net/dto/Message.java @@ -0,0 +1,68 @@ +package com.ydd.sportfaceid.net.dto; + +import com.google.gson.annotations.Expose; + +/** + *
上位机与通讯服务器的数据协议格式
+ * + * @author peakren + * @date 07/12/2017 9:57 PM + */ +public class Message extends BaseDto { + + private static final long serialVersionUID = -7944124768291562453L; + + /** + * 消息内容 + */ + @Expose + private MemberDto result; + + + @Expose + private FaceImageDto faceImage; + + /** + * 机器识别返回字符串 + */ + @Expose + private String content; + + + public int getDoor() { + return door; + } + + public void setDoor(int door) { + this.door = door; + } + + @Expose + private int door; + + + public MemberDto getResult() { + return result; + } + + public void setResult(MemberDto result) { + this.result = result; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public FaceImageDto getFaceImage() { + return faceImage; + } + + public void setFaceImage(FaceImageDto faceImage) { + this.faceImage = faceImage; + } + +} diff --git a/app/src/main/java/com/ydd/sportfaceid/receiver/BootCompletedReceiver.java b/app/src/main/java/com/ydd/sportfaceid/receiver/BootCompletedReceiver.java new file mode 100644 index 0000000..5bad737 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/receiver/BootCompletedReceiver.java @@ -0,0 +1,30 @@ +package com.ydd.sportfaceid.receiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +import com.ydd.sportfaceid.MainActivity; + +/** + *

Copyright © 2017 Zego. All rights reserved.

+ * + * @author realuei on 01/11/2017. + */ + +public class BootCompletedReceiver extends BroadcastReceiver { + + private final String TAG = "YDD_SPORT"; + + @Override + public void onReceive(Context context, Intent intent) { + try { + Intent i = new Intent(context, MainActivity.class); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(i); + } catch (Exception e) { + Log.e(TAG, "start the guard service failed.", e); + } + } +} diff --git a/app/src/main/java/com/ydd/sportfaceid/service/ClientService.java b/app/src/main/java/com/ydd/sportfaceid/service/ClientService.java new file mode 100644 index 0000000..af03268 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/service/ClientService.java @@ -0,0 +1,66 @@ +package com.ydd.sportfaceid.service; + +import android.app.IntentService; +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; +import android.support.annotation.Nullable; +import android.util.Log; + +import com.ydd.sportfaceid.StartApplication; +import com.ydd.sportfaceid.net.ClientThread; +import com.ydd.sportfaceid.websocket.FaceWsClient; +import com.ydd.sportfaceid.websocket.FaceWsClientService; + +/** + * 启动socker和websocket服务 + * + * @author peakren + * @date 05/12/2017 10:25 PM + */ +public class ClientService extends IntentService { + + public ClientService() { + super("new cocket"); + } + + @Override + public void onCreate() { + super.onCreate(); +//启动服务器socket连接 + + Log.d("sander", "clientThread run"); + StartApplication.executor.execute(new Runnable() { + @Override + public void run() { + ClientThread.getInstance().run(); + } + }); + } + +// @Override +// public int onStartCommand(Intent intent, int flags, int startId) { +// return super.onStartCommand(intent, flags, startId); +// } +// +// @Override +// public void onDestroy() { +// super.onDestroy(); +// } +// +// @Override +// public IBinder onBind(Intent intent) { +// return null; +// } + + @Override + protected void onHandleIntent(Intent intent) { + /** + * 启动face++ websocket连接 + */ + FaceWsClientService.getInstance().start(); + + Log.d("sander","这里在重复启动hanglde intent service"); + } + +} diff --git a/app/src/main/java/com/ydd/sportfaceid/service/MessageService.java b/app/src/main/java/com/ydd/sportfaceid/service/MessageService.java new file mode 100644 index 0000000..5f50bcb --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/service/MessageService.java @@ -0,0 +1,181 @@ +package com.ydd.sportfaceid.service; + + +import android.util.Base64; +import android.util.Log; +import android.widget.Toast; + +import com.google.gson.Gson; +import com.ydd.sportfaceid.BuildConfig; +import com.ydd.sportfaceid.StartApplication; +import com.ydd.sportfaceid.event.FaceidEvent; +import com.ydd.sportfaceid.net.Cmd; +import com.ydd.sportfaceid.net.dto.AddFaceResponse; +import com.ydd.sportfaceid.net.dto.FaceImageDto; +import com.ydd.sportfaceid.net.dto.Message; +import com.ydd.sportfaceid.session.ClientTcpSession; +import com.ydd.sportfaceid.utils.AppLogger; +import com.ydd.sportfaceid.utils.DeviceIdUtil; +import com.ydd.sportfaceid.utils.JsonMapper; + +import org.greenrobot.eventbus.EventBus; + +import java.io.Console; +import java.io.IOException; +import java.util.UUID; + +import Net.PC15.Command.CommandDetial; +import Net.PC15.Connector.ConnectorAllocator; +import Net.PC15.Connector.E_ControllerType; +import Net.PC15.Connector.TCPClient.TCPClientDetial; +import Net.PC15.FC8800.Command.Door.OpenDoor; +import Net.PC15.FC8800.Command.Door.Parameter.OpenDoor_Parameter; +import Net.PC15.FC8800.FC8800Identity; +import okhttp3.MediaType; +import okhttp3.MultipartBody; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okhttp3.ResponseBody; + +/** + * 消息服务 + * MessageService.java + * + * @author peakren + * @date 2018/12/20 6:00 PM + */ +public class MessageService { + + private final static String TAG = "MessageService"; + + + static private MessageService sInstance; + + static public MessageService getInstance() { + if (sInstance == null) { + synchronized (ClientTcpSession.class) { + if (sInstance == null) { + sInstance = new MessageService(); + } + } + } + return sInstance; + } + + /** + * 解析并执行接受服务器消息 + * + * @param message + */ + public void execute(Message message) { + if (null == message) { + return; + } + Cmd cmd = Cmd.getCmd(message.getCmdId()); + switch (cmd) { + case HB: + break; + case FACEID: + EventBus.getDefault().post(new FaceidEvent(message.getResult())); + break; + //识别结果返回 + case OPEN_DOOR: + AppLogger.getInstance().writeLog("----receive open door cmd----"); + StartApplication.executor.execute(new Runnable() { + @Override + public void run() { + openDoor(message.getDoor()); + } + }); + break; + + //接收人脸照片 + case RECEV_FACE_IMAGE: + //获取图片内容 + String imageBase64 = message.getContent(); + StartApplication.executor.execute(new Runnable() { + @Override + public void run() { + try { + Integer faceId = uploadFace(imageBase64); + Message sendMsg = new Message(); + sendMsg.setCmdId(Cmd.RECEV_FACE_IMAGE_R.id); + sendMsg.setDeviceId(DeviceIdUtil.generateDeviceId(StartApplication.getAppContext())); + FaceImageDto faceImage = new FaceImageDto(); + faceImage.setFaceId(faceId); + if (sendMsg.getFaceImage() != null) { + faceImage.setMemberId(sendMsg.getFaceImage().getMemberId()); + } + sendMsg.setFaceImage(faceImage); + //返回上传结果 + ClientTcpSession.getInstance().send(sendMsg); + } catch (Exception e) { + Log.e(TAG, "upload face image error..."); + } + } + }); + break; + } + + } + + /** + * 门禁开门 + */ + public void openDoor(int ivalue) { + try { + AppLogger.getInstance().writeLog("----init open door tcp ----"); + ConnectorAllocator connector = ConnectorAllocator.GetAllocator(); + TCPClientDetial tcpClientDetial = new TCPClientDetial(BuildConfig.DOOR_SERVER_IP, Integer.valueOf(BuildConfig.DOOR_SERVER_PORT)); + connector.GetCommandCount(tcpClientDetial); + connector.OpenForciblyConnect(tcpClientDetial); + CommandDetial detial = new CommandDetial(); + detial.Connector = tcpClientDetial; + detial.Identity = new FC8800Identity(BuildConfig.DOOR_SN, BuildConfig.DOOR_PWD, E_ControllerType.FC8900); + OpenDoor_Parameter openDoor_parameter = new OpenDoor_Parameter(detial); + openDoor_parameter.Door.SetDoor(ivalue, 1); + OpenDoor openDoor = new OpenDoor(openDoor_parameter); + boolean command = connector.AddCommand(openDoor); + if (openDoor.getIsTimeout()) { + AppLogger.getInstance().writeLog("----open door timeout ----"); + } + } catch (Exception e) { + AppLogger.getInstance().writeLog("----open door error ----", e.getMessage()); + } + } + + /** + * 上传识别头像 + * + * @param faceImageBase64 + */ + public Integer uploadFace(String faceImageBase64) throws IOException { + String url = "http://192.168.1.111/subject/photo"; + byte[] buffer = Base64.decode(faceImageBase64, Base64.DEFAULT); + OkHttpClient client = new OkHttpClient(); + RequestBody requestBody = new MultipartBody.Builder() + .setType(MultipartBody.FORM) + .addFormDataPart("photo", System.currentTimeMillis() + "", RequestBody.create(MediaType.parse("multipart/form-data"), buffer)) + .build(); + Request request = new Request.Builder() + .header("Authorization", "Client-ID " + UUID.randomUUID()) + .url(url) + .post(requestBody) + .build(); + + Response response = client.newCall(request).execute(); + if (!response.isSuccessful()) { + throw new IOException("Unexpected code " + response); + } + + ResponseBody responseBody = response.body(); + AddFaceResponse faceResponse = JsonMapper.fromJson(responseBody.string(), AddFaceResponse.class); + if (faceResponse.getCode() == 0) { + return faceResponse.getData().getId(); + } + return -1; + } + +} diff --git a/app/src/main/java/com/ydd/sportfaceid/session/ClientTcpSession.java b/app/src/main/java/com/ydd/sportfaceid/session/ClientTcpSession.java new file mode 100644 index 0000000..b2f8934 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/session/ClientTcpSession.java @@ -0,0 +1,53 @@ +package com.ydd.sportfaceid.session; + + +import com.ydd.sportfaceid.net.dto.Message; + +import io.netty.channel.ChannelHandlerContext; + +/** + * 通讯服务器session持久化 + * + * @author peakren + * @date 07/12/2017 10:42 PM + */ +public class ClientTcpSession { + + private static ChannelHandlerContext context; + + static private ClientTcpSession sInstance; + + static public ClientTcpSession getInstance() { + if (sInstance == null) { + synchronized (ClientTcpSession.class) { + if (sInstance == null) { + sInstance = new ClientTcpSession(); + } + } + } + return sInstance; + } + + public ChannelHandlerContext getContext() { + return this.context; + } + + public void setContext(ChannelHandlerContext context) { + this.context = context; + } + + + public void send(Message message) { + if (context != null) { + context.writeAndFlush(message); + } + } + + + public void close() { + if (context != null) { + context.close(); + context = null; + } + } +} diff --git a/app/src/main/java/com/ydd/sportfaceid/setting/SDSettingActivity.java b/app/src/main/java/com/ydd/sportfaceid/setting/SDSettingActivity.java new file mode 100644 index 0000000..df5eb4d --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/setting/SDSettingActivity.java @@ -0,0 +1,85 @@ +package com.ydd.sportfaceid.setting; + +import android.content.Intent; +import android.media.Image; +import android.support.annotation.BinderThread; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.View; +import android.widget.ImageView; + +import com.ydd.sportfaceid.MainActivity; +import com.ydd.sportfaceid.R; +import com.ydd.sportfaceid.config.SDAppConfig; +import com.ydd.sportfaceid.main.SDBaseActivity; + +import butterknife.BindView; +import butterknife.OnClick; + +public class SDSettingActivity extends SDBaseActivity { + + + @BindView(R.id.camer_check_1) + ImageView camer_check_1_image_view; + + @BindView(R.id.camer_check_2) + ImageView camer_check_2_image_view; + + + private int selectedCameraIndex; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_sdsetting); + + this.configView(); + this.configData(); + } + + + private void configView(){ + this.camer_check_1_image_view.setVisibility(View.GONE); + this.camer_check_2_image_view.setVisibility(View.GONE); + } + private void configData(){ + this.setSelectedCameraIndex(SDAppConfig.getInstance().getCurrent_selected_camera()); + } + public void setSelectedCameraIndex(int selectedCameraIndex) { + this.selectedCameraIndex = selectedCameraIndex; + if (this.selectedCameraIndex == 0 ){ + this.camer_check_2_image_view.setVisibility(View.GONE); + this.camer_check_1_image_view.setVisibility(View.VISIBLE); + }else if (this.selectedCameraIndex == 1){ + this.camer_check_2_image_view.setVisibility(View.VISIBLE); + this.camer_check_1_image_view.setVisibility(View.GONE); + } + SDAppConfig.getInstance().setCurrent_selected_camera(selectedCameraIndex); + } + + + public void onGoToMainAction(){ + finish(); + } + + @OnClick({R.id.back_button,R.id.camer_cell_1, R.id.camer_cell_2}) void onCilck(View view){ + switch (view.getId()){ + case R.id.back_button: + this.onGoToMainAction(); + break; + case R.id.camer_cell_1: + this.setSelectedCameraIndex(0); + break; + case R.id.camer_cell_2: + this.setSelectedCameraIndex(1); + break; + } + } + + @Override + public void onBackPressed() { + super.onBackPressed(); + this.onGoToMainAction(); + } +} diff --git a/app/src/main/java/com/ydd/sportfaceid/utils/AppLogger.java b/app/src/main/java/com/ydd/sportfaceid/utils/AppLogger.java new file mode 100644 index 0000000..d80dfe1 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/utils/AppLogger.java @@ -0,0 +1,297 @@ +package com.ydd.sportfaceid.utils; + +import android.content.Context; +import android.os.Environment; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Message; +import android.text.TextUtils; +import android.util.Log; +import com.ydd.sportfaceid.StartApplication; +import java.io.BufferedWriter; +import java.io.Closeable; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + *

Copyright © 2017 Zego. All rights reserved.

+ * + * @author realuei on 26/10/2017. + */ + +public class AppLogger { + + static final private String TAG = "YDD_WWJ"; + + static final private int MSG_ID_WRITE_LOG = 1; + static final private int MSG_ID_CLEAR_LOG = 2; + + static final private int SINGLE_LOG_FILE_MAX_SIZE = 100 * 1024 * 1024; // 100M + + static private String LOG_FILE_NAME = "face_sport.log"; + static private String LOG_FILE_NAME_BAK = "face_sport_2.log"; + + static private AppLogger sInstance; + + final private LinkedList mLogList = new LinkedList<>(); + final private List mUnmodifiableList = Collections.unmodifiableList(mLogList); + + private HandlerThread mLogThread; + private Handler mLogHandler; + + private ArrayList mListeners = new ArrayList<>(); + + private File mLogFile; + private Writer mLogWriter; + + private AppLogger() { + initLogFile(); + + mLogThread = new HandlerThread("ydd_face_logger"); + mLogThread.start(); + + mLogHandler = new Handler(mLogThread.getLooper()) { + + private int loopCnt = 0; + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_ID_WRITE_LOG: { + flushLogFileIfNeed(); + + String message = (String) msg.obj; + + Log.d(TAG, message); + + String message_with_time = String.format("%s %s", TimeUtil.getLogStr(), message); + mLogList.addFirst(message_with_time); + safeWriteLog2File(message_with_time); + + for (OnLogChangedListener listener : mListeners) { + listener.onLogDataChanged(); + } + } + break; + + case MSG_ID_CLEAR_LOG: { + mLogList.clear(); + for (OnLogChangedListener listener : mListeners) { + listener.onLogDataChanged(); + } + } + break; + } + + } + + private void flushLogFileIfNeed() { + loopCnt++; + if (loopCnt >= 10) { + loopCnt = 0; + if (mLogWriter != null) { + try { + mLogWriter.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + int logLength = mLogList.size(); + if (logLength > 1500) { + for (int i = logLength - 1; i >= 1000; i--) { + mLogList.remove(i); + } + + if (mLogFile.length() >= SINGLE_LOG_FILE_MAX_SIZE) { + initLogFile(); + } + } + } + }; + } + + static public void setLogFileName(String logName, String bakLogName) { + LOG_FILE_NAME = logName; + LOG_FILE_NAME_BAK = bakLogName; + } + + static public AppLogger getInstance() { + if (sInstance == null) { + synchronized (AppLogger.class) { + if (sInstance == null) { + sInstance = new AppLogger(); + } + } + } + return sInstance; + } + + private void initLogFile() { + String logPath = getLogPath(StartApplication.getAppContext()); + File logFile = new File(logPath, LOG_FILE_NAME); + if (logFile.exists() && logFile.length() >= SINGLE_LOG_FILE_MAX_SIZE) { // 日志文件存在,且文件尺寸大于 10M 时,备份日志 + File bakLogFile = new File(logPath, LOG_FILE_NAME_BAK); + if (bakLogFile.exists()) { + bakLogFile.delete(); + } + + safeCloseStream(mLogWriter); + logFile.renameTo(bakLogFile); + } + + mLogFile = new File(logPath, LOG_FILE_NAME); + try { + safeCloseStream(mLogWriter); + + mLogWriter = new BufferedWriter(new FileWriter(mLogFile, true)); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void safeWriteLog2File(String content) { + if (mLogWriter == null) return; + + try { + mLogWriter.write(content); + mLogWriter.write("\r\n"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void safeCloseStream(Closeable stream) { + if (stream != null) { + try { + stream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public void writeLog(final String format, final Object... args) { + String data; + + if (args.length == 0) { + data = format; + } else { + data = String.format(format, args); + } + + Message msg = Message.obtain(); + msg.what = MSG_ID_WRITE_LOG; + msg.obj = data; + mLogHandler.sendMessage(msg); + } + + /** + * 返回只读日志列表 + * + * @return 只读日志列表 + */ + public List getAllLog() { + return mUnmodifiableList; + } + + public void clearLog() { + mLogHandler.sendEmptyMessage(MSG_ID_CLEAR_LOG); + } + + public void registerLogChangedListener(final OnLogChangedListener listener) { + if (listener == null) return; + + mLogHandler.post(new Runnable() { + @Override + public void run() { + boolean inExists = false; + for (OnLogChangedListener _listener : mListeners) { + if (listener == _listener) { + inExists = true; + break; + } + } + + if (!inExists) { + mListeners.add(listener); + } + } + }); + } + + public void unregisterLogChangedListener(final OnLogChangedListener listener) { + if (listener == null) return; + + mLogHandler.post(new Runnable() { + @Override + public void run() { + int idx = -1; + for (int i = 0; i < mListeners.size(); i++) { + if (mListeners.get(i) == listener) { + idx = i; + break; + } + } + + if (idx >= 0) { + mListeners.remove(idx); + } + } + }); + } + + public interface OnLogChangedListener { + void onLogDataChanged(); + } + + + public static String getLogPath(Context context) { + if (context == null) { + return null; + } else { + File dir = null; + File filesDir; + String filesDirPath; + if (Environment.getExternalStorageState().equals("mounted")) { + filesDir = context.getExternalFilesDir((String) null); + if (filesDir != null) { + filesDirPath = filesDir.getAbsolutePath(); + if (!TextUtils.isEmpty(filesDirPath)) { + dir = new File(filesDirPath); + } + } + } + + if (dir == null) { + filesDir = context.getFilesDir(); + if (filesDir != null) { + filesDirPath = filesDir.getAbsolutePath(); + if (!TextUtils.isEmpty(filesDirPath)) { + dir = new File(filesDirPath); + } + } + } + + if (dir == null) { + return null; + } else { + if (!dir.exists()) { + dir.mkdirs(); + if (!dir.exists()) { + return null; + } + } + + return dir.getAbsolutePath().toString(); + } + } + } +} diff --git a/app/src/main/java/com/ydd/sportfaceid/utils/AppUtil.java b/app/src/main/java/com/ydd/sportfaceid/utils/AppUtil.java new file mode 100644 index 0000000..399c19b --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/utils/AppUtil.java @@ -0,0 +1,50 @@ +package com.ydd.sportfaceid.utils; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; + +/** + * Created by peakren on 07/12/2017. + */ + +public class AppUtil { + + /** + * get App versionCode + * + * @param context + * @return + */ + public static String getVersionCode(Context context) { + PackageManager packageManager = context.getPackageManager(); + PackageInfo packageInfo; + String versionCode = ""; + try { + packageInfo = packageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_CONFIGURATIONS); + versionCode = packageInfo.versionCode + ""; + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + return versionCode; + } + + /** + * get App versionName + * + * @param context + * @return + */ + public static String getVersionName(Context context) { + PackageManager packageManager = context.getPackageManager(); + PackageInfo packageInfo; + String versionName = ""; + try { + packageInfo = packageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_CONFIGURATIONS); + versionName = packageInfo.versionName; + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + return versionName; + } +} diff --git a/app/src/main/java/com/ydd/sportfaceid/utils/DeviceIdUtil.java b/app/src/main/java/com/ydd/sportfaceid/utils/DeviceIdUtil.java new file mode 100644 index 0000000..a9d0b25 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/utils/DeviceIdUtil.java @@ -0,0 +1,106 @@ +package com.ydd.sportfaceid.utils; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; +import android.os.Build; +import android.provider.Settings; +import android.text.TextUtils; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.LineNumberReader; +import java.lang.reflect.Method; +import java.util.UUID; + +/** + *

Copyright © 2017 Zego. All rights reserved.

+ * + * @author realuei on 08/11/2017. + */ + +public class DeviceIdUtil { + static final private String INVALID_SERIAL_NUMBER = "12345678900"; + + @SuppressLint("MissingPermission") + static final public String generateDeviceId(Context context) { + String deviceId = getEthernetMac(); + if (!TextUtils.isEmpty(deviceId) && !Build.UNKNOWN.equals(deviceId)) { + return deviceId; + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + deviceId = Build.SERIAL; + } else { + deviceId = Build.SERIAL; + } + + if (!Build.UNKNOWN.equals(deviceId) && !INVALID_SERIAL_NUMBER.equals(deviceId)) { + return deviceId; + } + + try { + Class c = Class.forName("android.os.SystemProperties"); + Method get = c.getMethod("get", String.class, String.class ); + deviceId = (String)(get.invoke(c, "ro.serialno", Build.UNKNOWN)); + } catch (Exception e) { + deviceId = null; + } + + if (!TextUtils.isEmpty(deviceId) && !Build.UNKNOWN.equals(deviceId) && !INVALID_SERIAL_NUMBER.equals(deviceId)) { + return deviceId; + } + + deviceId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); + if (!"9774d56d682e549c".equals(deviceId) && !INVALID_SERIAL_NUMBER.equals(deviceId) + && !TextUtils.isEmpty(deviceId) && deviceId.length() > 6) { + return deviceId; + } + + // wifi mac地址 + WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + WifiInfo info = wifi.getConnectionInfo(); + String wifiMac = info.getMacAddress(); + if(!TextUtils.isEmpty(wifiMac)){ + return String.format("w%s", wifiMac.replace(":", "")); + } + + return UUID.randomUUID().toString().replace("-", ""); + } + + /** + * 获取有线网卡的 MAC 地址 + * @return + */ + static private String getEthernetMac() { + String macSerial = null; + String str = ""; + try { + Process pp = Runtime.getRuntime().exec("cat /sys/class/net/eth0/address "); + InputStreamReader ir = new InputStreamReader(pp.getInputStream()); + LineNumberReader input = new LineNumberReader(ir); + + for (; null != str; ) { + str = input.readLine(); + if (str != null) { + macSerial = str.trim();// 去空格 + break; + } + } + } catch (IOException ex) { + // 赋予默认值 + ex.printStackTrace(); + + return Build.UNKNOWN; + } + + if (macSerial != null && macSerial.length() > 0) + macSerial = macSerial.replaceAll(":", ""); + else { + return Build.UNKNOWN; + } + + return macSerial; + } +} diff --git a/app/src/main/java/com/ydd/sportfaceid/utils/EggClickUtil.java b/app/src/main/java/com/ydd/sportfaceid/utils/EggClickUtil.java new file mode 100644 index 0000000..3f49f8c --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/utils/EggClickUtil.java @@ -0,0 +1,39 @@ +package com.ydd.sportfaceid.utils; + +import android.os.SystemClock; + +public class EggClickUtil { + + final static int COUNTS = 5;//点击次数 + final static long DURATION = 1 * 1000;//规定有效时间 + long[] mHits = new long[COUNTS]; + + public void setEggClickListener(onEggClickListener eggClickListener) { + this.eggClickListener = eggClickListener; + } + + private onEggClickListener eggClickListener; + + public EggClickUtil(){ + + } + public EggClickUtil(onEggClickListener listener){ + this.eggClickListener = listener; + } + + + public void checkoutHideFunction(){ + System.arraycopy(mHits, 1, mHits, 0, mHits.length - 1); + mHits[mHits.length - 1] = SystemClock.uptimeMillis(); + if (mHits[0] >= (SystemClock.uptimeMillis() - DURATION)) { + mHits = new long[COUNTS]; + if (this.eggClickListener != null){ + this.eggClickListener.onClickAction(); + } + } + } + + public interface onEggClickListener { + void onClickAction(); + } +} diff --git a/app/src/main/java/com/ydd/sportfaceid/utils/JsonMapper.java b/app/src/main/java/com/ydd/sportfaceid/utils/JsonMapper.java new file mode 100644 index 0000000..3b88d02 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/utils/JsonMapper.java @@ -0,0 +1,62 @@ +package com.ydd.sportfaceid.utils; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; + +import java.lang.reflect.Type; +import java.util.List; + +/** + * Created by ranfi on 12/9/14. + */ +public class JsonMapper { + + private final static Gson gson; + + static { + GsonBuilder builder = new GsonBuilder(); + builder.setDateFormat("yyyy-MM-dd HH:mm:ss"); + builder.excludeFieldsWithoutExposeAnnotation(); + gson = builder.create(); + } + + private JsonMapper() { + + } + + /** + * Object可以是POJO,也可以是Collection或数组。 如果对象为Null, 返回"null". 如果集合为空集合, 返回"[]". + * + * @param obj + * @return + */ + public static String toJson(Object obj) { + return gson.toJson(obj); + } + + + public static String toJson(Object obj, Type type) { + return gson.toJson(obj, type); + } + + /** + * 反序列化POJO或简单Collection如List. + *

+ * 如果JSON字符串为Null或"null"字符串, 返回Null. 如果JSON字符串为"[]", 返回空集合. + *

+ * 如需反序列化复杂Collection如List, 请使用fromJson(String, JavaType) + */ + public static T fromJson(String jsonValue, Class clazz) { + return gson.fromJson(jsonValue, clazz); + } + + public static T fromJson(String jsonValue, Type type) { + return gson.fromJson(jsonValue, type); + } + + public static List fromJson(String jsonValue) { + return gson.fromJson(jsonValue, new TypeToken>() { + }.getType()); + } +} diff --git a/app/src/main/java/com/ydd/sportfaceid/utils/SharedPreferencesUtil.java b/app/src/main/java/com/ydd/sportfaceid/utils/SharedPreferencesUtil.java new file mode 100644 index 0000000..3e3b24a --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/utils/SharedPreferencesUtil.java @@ -0,0 +1,135 @@ +package com.ydd.sportfaceid.utils; + +import android.content.Context; +import android.content.SharedPreferences; + +import com.ydd.sportfaceid.BuildConfig; +import com.ydd.sportfaceid.StartApplication; + + +/** + * Created by hehelt on 15/12/23. + *

+ * 本地SharePreference存储帮助类 + */ +public class SharedPreferencesUtil { + + private static SharedPreferences infoShare; + + private static SharedPreferences serverShare; + + + //初始化 + private static void initInfoShare() { + if (infoShare == null) { + infoShare = StartApplication.getAppContext().getSharedPreferences("info", Context.MODE_PRIVATE); + } + } + + private static void initServerShare() { + if (serverShare == null) { + serverShare = StartApplication.getAppContext().getSharedPreferences("server", Context.MODE_PRIVATE); + } + } + + + public static boolean setServerIpAndPort(String ip, int port) { + initServerShare(); + if (getServerIp().equals(ip) && getServerPort() == port) { + return false; + } + serverShare.edit().putString("serverIp", ip).putInt("serverPort", port).apply(); + return true; + } + + public static String getServerIp() { + initServerShare(); + return serverShare.getString("serverIp", BuildConfig.SERVER_IP); + } + + public static int getServerPort() { + initServerShare(); + return serverShare.getInt("serverPort", Integer.parseInt(BuildConfig.SERVER_PORT)); + } + + /** + * 设置face++的连接地址和端口 + * + * @param url + * @return + */ + public static boolean setFaceidWsUrl(String url) { + initServerShare(); + if (getFaceidWsUrl().equals(url)) { + return false; + } + serverShare.edit().putString("faceidWsUrl", url).apply(); + return true; + } + + public static String getFaceidWsUrl() { + initServerShare(); + return serverShare.getString("faceidWsUrl", BuildConfig.FACEID_WS_URL); + } + + /** + * 设置门禁的连接地址和端口 + * + * @param ip + * @param port + * @return + */ + public static boolean setDoorServerIpAndPort(String ip, int port) { + initServerShare(); + if (getDoorServerIp().equals(ip) && getDoorServerPort() == port) { + return false; + } + serverShare.edit().putString("doorServerIp", ip).putInt("doorServerPort", port).apply(); + return true; + } + + public static String getDoorServerIp() { + initServerShare(); + return serverShare.getString("doorServerIp", BuildConfig.DOOR_SERVER_IP); + } + + public static int getDoorServerPort() { + initServerShare(); + return serverShare.getInt("doorServerPort", Integer.parseInt(BuildConfig.DOOR_SERVER_PORT)); + } + + + public static SharedPreferences netConfig; + + public static void setIsNetConfig(boolean isSet) { + netConfig = StartApplication.getAppContext().getSharedPreferences("netConfig", Context.MODE_PRIVATE); + netConfig.edit().putBoolean("flag", isSet).apply(); + } + + public static boolean getNetConfig() { + netConfig = StartApplication.getAppContext().getSharedPreferences("netConfig", Context.MODE_PRIVATE); + return netConfig.getBoolean("flag", false); + } + + public static void saveIp(String ip) { + if (null != ip && !"".equals(ip)) { + initLocalIp(); + localIp.edit().putString("ip", ip).apply(); + } + } + + public static String getLocalIp() { + initLocalIp(); + String ip = localIp.getString("ip", "0.0.0.0"); + return ip; + } + + public static void initLocalIp() { + if (localIp == null) { + localIp = StartApplication.getAppContext().getSharedPreferences("localIp", Context.MODE_PRIVATE); + } + } + + public static SharedPreferences localIp; + +} diff --git a/app/src/main/java/com/ydd/sportfaceid/utils/TimeUntil.java b/app/src/main/java/com/ydd/sportfaceid/utils/TimeUntil.java new file mode 100644 index 0000000..2d094f6 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/utils/TimeUntil.java @@ -0,0 +1,48 @@ +package com.ydd.sportfaceid.utils; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +/** + * Created by sandershan on 2018/11/27. + */ + +public class TimeUntil { + public static String getWeakDay(Date date){ + String Week = ""; + Calendar c = Calendar.getInstance(); + try { + + c.setTime(date); + + } catch (Exception ex ){ + ex.printStackTrace(); + } + if (c.get(Calendar.DAY_OF_WEEK) == 1) { + Week += "天"; + } + if (c.get(Calendar.DAY_OF_WEEK) == 2) { + Week += "一"; + } + if (c.get(Calendar.DAY_OF_WEEK) == 3) { + Week += "二"; + } + if (c.get(Calendar.DAY_OF_WEEK) == 4) { + Week += "三"; + } + if (c.get(Calendar.DAY_OF_WEEK) == 5) { + Week += "四"; + } + if (c.get(Calendar.DAY_OF_WEEK) == 6) { + Week += "五"; + } + if (c.get(Calendar.DAY_OF_WEEK) == 7) { + Week += "六"; + } + + + + return "星期" + Week; + } +} diff --git a/app/src/main/java/com/ydd/sportfaceid/utils/TimeUtil.java b/app/src/main/java/com/ydd/sportfaceid/utils/TimeUtil.java new file mode 100644 index 0000000..cd92376 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/utils/TimeUtil.java @@ -0,0 +1,23 @@ +package com.ydd.sportfaceid.utils; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + *

Copyright © 2017 Zego. All rights reserved.

+ * + * @author realuei on 24/10/2017. + */ + +public class TimeUtil { + static final private SimpleDateFormat sFormat = new SimpleDateFormat("yyMMddHHmmssSSS"); + static final private SimpleDateFormat sLogFormat = new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); + + static public String getNowTimeStr() { + return sFormat.format(new Date()); + } + + static public String getLogStr() { + return sLogFormat.format(new Date()); + } +} diff --git a/app/src/main/java/com/ydd/sportfaceid/view/SDGustInfoView.java b/app/src/main/java/com/ydd/sportfaceid/view/SDGustInfoView.java new file mode 100644 index 0000000..86a3059 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/view/SDGustInfoView.java @@ -0,0 +1,140 @@ +package com.ydd.sportfaceid.view; + +import android.content.Context; +import android.graphics.Bitmap; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + + +import com.ydd.sportfaceid.R; +import com.ydd.sportfaceid.utils.TimeUntil; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Timer; +import java.util.TimerTask; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; +import rx.Observable; +import rx.Subscriber; +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; + +/** + * Created by sandershan on 2018/12/4. + */ + +public class SDGustInfoView extends RelativeLayout { + + public Context mContext; + + public static String mMemberName =""; + + @BindView(R.id.app_logo_imageview) + ImageView app_logo_imageview; + + @BindView(R.id.time_label) + TextView time_label; + @BindView(R.id.date_label) + TextView date_label; + + @BindView(R.id.app_member_name_label) + TextView app_member_name_label; + + private Timer mTimerOutput; + + public void setLogo(String logo) { + this.logo = logo; + + } + + private String logo; + + public void setMemberName(String memberName) { + this.app_member_name_label.setText(memberName); + } + + + + public SDGustInfoView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + this.mContext = context; + LayoutInflater.from(context).inflate(R.layout.layout_guest_info_top, this); + ButterKnife.bind(this); + configView(); + sdConfigData(); + startRunUpdateTime(); + + } + + public void configView(){ + + this.app_member_name_label.setText(""); + } + + public void sdConfigData(){ + Date now_date = new Date(); + SimpleDateFormat time_format =new SimpleDateFormat("HH:mm"); + String time_string = time_format.format(now_date); + time_label.setText(time_string); + SimpleDateFormat date_format =new SimpleDateFormat("yyyy/MM/dd"); + String date_string = date_format.format(now_date); + String weak_string = TimeUntil.getWeakDay(now_date); + date_label.setText(date_string + " " + weak_string); + } + + public void startRunUpdateTime(){ + mTimerOutput = new Timer(); + mTimerOutput.schedule(new TimerTask() { + @Override + public void run() { //定时器,更新日志 + Observable.create(new Observable.OnSubscribe() { + + @Override + public void call(Subscriber subscriber) { + subscriber.onNext(null); + subscriber.onCompleted(); + } + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber() { + + @Override + public void onCompleted() { + + } + + @Override + public void onError(Throwable e) { + + } + + @Override + public void onNext(Object o) { + sdConfigData(); + } + }); + } + }, 100, 1000); + } + + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (mTimerOutput != null){ + this.mTimerOutput.cancel(); + this.mTimerOutput = null; + } + + } + +} diff --git a/app/src/main/java/com/ydd/sportfaceid/websocket/FaceWsClient.java b/app/src/main/java/com/ydd/sportfaceid/websocket/FaceWsClient.java new file mode 100644 index 0000000..a1b3f25 --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/websocket/FaceWsClient.java @@ -0,0 +1,93 @@ +package com.ydd.sportfaceid.websocket; + + +import android.util.Log; + +import com.google.gson.Gson; +import com.tencent.bugly.crashreport.CrashReport; +import com.ydd.sportfaceid.StartApplication; +import com.ydd.sportfaceid.config.SDAppConfig; +import com.ydd.sportfaceid.event.FaceidEvent; +import com.ydd.sportfaceid.net.Cmd; +import com.ydd.sportfaceid.net.dto.FaceRecognizeResponse; +import com.ydd.sportfaceid.net.dto.Message; +import com.ydd.sportfaceid.session.ClientTcpSession; +import com.ydd.sportfaceid.utils.DeviceIdUtil; + +import org.greenrobot.eventbus.EventBus; +import org.java_websocket.client.WebSocketClient; +import org.java_websocket.drafts.Draft; +import org.java_websocket.handshake.ServerHandshake; + +import java.net.URI; +import java.util.Map; + + +/** + * face++ WS连接客户端 + * FaceWsClient.java + * + * @author peakren + * @date 2019/4/15 12:51 PM + */ +public class FaceWsClient extends WebSocketClient { + + private final static String TAG = "FaceWsClient"; + private Gson gson = new Gson(); + + public FaceWsClient(URI serverUri, Draft draft) { + super(serverUri, draft); + } + + public FaceWsClient(URI serverURI) { + super(serverURI); + } + + public FaceWsClient(URI serverUri, Map httpHeaders) { + super(serverUri, httpHeaders); + } + + @Override + public void onOpen(ServerHandshake handshakedata) { + Log.i(TAG, "opened connection"); + } + + @Override + public void onMessage(String message) { + Log.i(TAG, "received: " + message); + + FaceRecognizeResponse faceRecognizeResponse = gson.fromJson(message, FaceRecognizeResponse.class); + if (faceRecognizeResponse.getType().equals("unrecognized")){ + Log.d("sander", "这是个陌生人,"); + FaceidEvent faceidEvent = new FaceidEvent(null); + EventBus.getDefault().post(faceidEvent); + }else { + Message sendMsg = new Message(); + sendMsg.setContent(message); + sendMsg.setCmdId(Cmd.FACEID_RESPONSE.id); + // 这里改成1和2,1是1号摄像头,2是2号摄像头 + int current_camera_index = SDAppConfig.getInstance().getCurrent_selected_camera(); + String device_ID = current_camera_index == 0 ? "1" : "2"; + CrashReport.postCatchedException(new Throwable("device_ID = " + device_ID + " message = " + message)); + sendMsg.setDeviceId(device_ID); + ClientTcpSession.getInstance().send(sendMsg); + } + +// FaceidEvent debugFace = new FaceidEvent(null); +// debugFace.isDebug = true; +// debugFace.msg = message; +// EventBus.getDefault().post(debugFace); + + } + + @Override + public void onClose(int code, String reason, boolean remote) { + Log.e(TAG, "Connection closed by " + (remote ? "remote peer" : "us") + " Code: " + code + " Reason: " + reason); + } + + @Override + public void onError(Exception ex) { + ex.printStackTrace(); + } + +} diff --git a/app/src/main/java/com/ydd/sportfaceid/websocket/FaceWsClientService.java b/app/src/main/java/com/ydd/sportfaceid/websocket/FaceWsClientService.java new file mode 100644 index 0000000..045499e --- /dev/null +++ b/app/src/main/java/com/ydd/sportfaceid/websocket/FaceWsClientService.java @@ -0,0 +1,63 @@ +package com.ydd.sportfaceid.websocket; + +import android.text.TextUtils; +import android.util.Log; + +import com.ydd.sportfaceid.BuildConfig; +import com.ydd.sportfaceid.StartApplication; +import com.ydd.sportfaceid.config.SDAppConfig; + +import java.net.URI; +import java.net.URLEncoder; +import java.util.concurrent.TimeUnit; + +public class FaceWsClientService { + + private final static String TAG = "FaceWsClientService"; + + private static FaceWsClientService instance; + + private String local_camer_service ; + FaceWsClient c = null; + public static FaceWsClientService getInstance() { + if (instance == null) { + synchronized (FaceWsClientService.class) { + if (instance == null) { + instance = new FaceWsClientService(); + } + } + } + return instance; + } + + + public void start() { + String rtspUrl = SDAppConfig.getInstance().getCurrentCameraUrl(); + + if (!TextUtils.isEmpty(local_camer_service)){ + if (local_camer_service.equals(rtspUrl)){ + return; + } + } + StartApplication.executor.execute(new Runnable() { + @Override + public void run() { + try { + if (c != null){ + c.closeBlocking(); + c = null; + } + local_camer_service = rtspUrl; +// String rtspUrl = "rtsp://192.168.1.161/user=admin&password=&channel=1&stream=0.sdp?"; + c = new FaceWsClient(new URI(BuildConfig.FACEID_WS_URL + URLEncoder.encode(rtspUrl, "UTF-8"))); + c.connectBlocking(5000, TimeUnit.MILLISECONDS); + } catch (Exception e) { + Log.e(TAG, e.toString()); + } + } + }); + + + } + +} diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/bg_withe_fillet.xml b/app/src/main/res/drawable/bg_withe_fillet.xml new file mode 100644 index 0000000..376ac81 --- /dev/null +++ b/app/src/main/res/drawable/bg_withe_fillet.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/memberwitebgview.xml b/app/src/main/res/drawable/memberwitebgview.xml new file mode 100644 index 0000000..f44ffcf --- /dev/null +++ b/app/src/main/res/drawable/memberwitebgview.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..cba5cf4 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,363 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_sdsetting.xml b/app/src/main/res/layout/activity_sdsetting.xml new file mode 100644 index 0000000..e3fa9e3 --- /dev/null +++ b/app/src/main/res/layout/activity_sdsetting.xml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_error_layout.xml b/app/src/main/res/layout/dialog_error_layout.xml new file mode 100644 index 0000000..b2d9e59 --- /dev/null +++ b/app/src/main/res/layout/dialog_error_layout.xml @@ -0,0 +1,32 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_guest_info_top.xml b/app/src/main/res/layout/layout_guest_info_top.xml new file mode 100644 index 0000000..9676c9b --- /dev/null +++ b/app/src/main/res/layout/layout_guest_info_top.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/app_img_ico_back.png b/app/src/main/res/mipmap-hdpi/app_img_ico_back.png new file mode 100644 index 0000000..4c3123e Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/app_img_ico_back.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..a2f5908 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..1b52399 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-hdpi/ico_check.png b/app/src/main/res/mipmap-hdpi/ico_check.png new file mode 100644 index 0000000..9544171 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ico_check.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..ff10afd Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..115a4c7 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..dcd3cd8 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..459ca60 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ico_add.png b/app/src/main/res/mipmap-xhdpi/ico_add.png new file mode 100644 index 0000000..9cb0e59 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ico_add.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ico_app_logo.png b/app/src/main/res/mipmap-xhdpi/ico_app_logo.png new file mode 100644 index 0000000..bad696a Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ico_app_logo.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ico_fi.png b/app/src/main/res/mipmap-xhdpi/ico_fi.png new file mode 100644 index 0000000..7eae6c2 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ico_fi.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ico_guest.png b/app/src/main/res/mipmap-xhdpi/ico_guest.png new file mode 100644 index 0000000..938376a Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ico_guest.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ico_line.png b/app/src/main/res/mipmap-xhdpi/ico_line.png new file mode 100644 index 0000000..7adae34 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ico_line.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ico_nex.png b/app/src/main/res/mipmap-xhdpi/ico_nex.png new file mode 100644 index 0000000..06e4b80 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ico_nex.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ico_phone.png b/app/src/main/res/mipmap-xhdpi/ico_phone.png new file mode 100644 index 0000000..d6150cd Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ico_phone.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ico_s_line.png b/app/src/main/res/mipmap-xhdpi/ico_s_line.png new file mode 100644 index 0000000..2e3a6ad Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ico_s_line.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ico_user.png b/app/src/main/res/mipmap-xhdpi/ico_user.png new file mode 100644 index 0000000..b47557c Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ico_user.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..8ca12fe Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..8e19b41 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..b824ebd Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..4c19a13 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..4e89f38 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,16 @@ + + + #020515 + #303F9F + #FF4081 + #1A191E + #ffffff + #35374A + #232637 + #E7EAF0 + #999999 + #1A191E + #4c000000 + #F3515C + #f4f4f4 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..b7f1878 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,11 @@ + + sport-faceid + 获取人脸信息中。。。 + 新用户注册 + 设置 + 当前设备为哪个摄像头服务? + 摄像头1 + 摄像头2 + 您好 \n 您尚未注册成为本智能运动场用户 \n请扫描门禁上张贴的场馆二维码进行注册后再试 + 如遇注册用户无法识别请联系场馆管理人员 + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..6d87cc7 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/app/src/test/java/com/ydd/sportfaceid/ExampleUnitTest.java b/app/src/test/java/com/ydd/sportfaceid/ExampleUnitTest.java new file mode 100644 index 0000000..8cd4e47 --- /dev/null +++ b/app/src/test/java/com/ydd/sportfaceid/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.ydd.sportfaceid; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/app/store b/app/store new file mode 100644 index 0000000..50d589d Binary files /dev/null and b/app/store differ diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..5333e8c --- /dev/null +++ b/build.gradle @@ -0,0 +1,25 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + + repositories { + google() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.1.4' + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/faceid.jks b/faceid.jks new file mode 100644 index 0000000..5da7877 Binary files /dev/null and b/faceid.jks differ diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..743d692 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,13 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..7a3265e Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..45c8a50 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Wed Dec 19 11:01:31 CST 2018 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..cccdd3d --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..f955316 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/install_apk.sh b/install_apk.sh new file mode 100644 index 0000000..729c72d --- /dev/null +++ b/install_apk.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +function print_error_then_exit { + echo "***** $1 *****" + exit 1 +} + +echo "Install app-$1-release.apk to device" +adb install -r app/build/outputs/apk/$1/release/app-$1-release.apk || print_error_then_exit "install error" + +echo "Start com.ydd.dm" +adb shell am start -a android.intent.action.MAIN -c android.intent.category.DEFAULT -n com.ydd.sportfaceid/.MainActivity || print_error_then_exit "start error" + +echo "Start finish." diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..e7b4def --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +include ':app'