diff --git a/app/build.gradle b/app/build.gradle index f98f5bc..9d60011 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,4 +56,10 @@ implementation 'com.google.code.gson:gson:2.8.6' //ZBar扫一扫 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' + //图片选择框架 + implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.5.0' + //图片压缩框架 + implementation 'top.zibin:Luban:1.1.8' } diff --git a/app/build.gradle b/app/build.gradle index f98f5bc..9d60011 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,4 +56,10 @@ implementation 'com.google.code.gson:gson:2.8.6' //ZBar扫一扫 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' + //图片选择框架 + implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.5.0' + //图片压缩框架 + implementation 'top.zibin:Luban:1.1.8' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2b7b378..c6065dc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/QMUI.Compat.NoActionBar" @@ -29,6 +30,16 @@ + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index f98f5bc..9d60011 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,4 +56,10 @@ implementation 'com.google.code.gson:gson:2.8.6' //ZBar扫一扫 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' + //图片选择框架 + implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.5.0' + //图片压缩框架 + implementation 'top.zibin:Luban:1.1.8' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2b7b378..c6065dc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/QMUI.Compat.NoActionBar" @@ -29,6 +30,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java new file mode 100644 index 0000000..e685c07 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java @@ -0,0 +1,18 @@ +package com.casic.birmm.hxrq.bean; + +/** + * @Author: Pengxh + * @Time: 2021/4/9 19:00 + * @Email: 290677893@qq.com + **/ +public class ImageBean { + private String image; + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } +} diff --git a/app/build.gradle b/app/build.gradle index f98f5bc..9d60011 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,4 +56,10 @@ implementation 'com.google.code.gson:gson:2.8.6' //ZBar扫一扫 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' + //图片选择框架 + implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.5.0' + //图片压缩框架 + implementation 'top.zibin:Luban:1.1.8' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2b7b378..c6065dc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/QMUI.Compat.NoActionBar" @@ -29,6 +30,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java new file mode 100644 index 0000000..e685c07 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java @@ -0,0 +1,18 @@ +package com.casic.birmm.hxrq.bean; + +/** + * @Author: Pengxh + * @Time: 2021/4/9 19:00 + * @Email: 290677893@qq.com + **/ +public class ImageBean { + private String image; + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java index 06c0332..d8b2ab7 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.model; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.utils.HttpConfig; import com.casic.birmm.hxrq.utils.retrofit.RetrofitServiceManager; @@ -33,7 +34,7 @@ } @Override - public Subscription sendRetrofitRequest(String image) { + public Subscription sendRetrofitRequest(ImageBean image) { Observable observable = RetrofitServiceManager.getFaceResult(HttpConfig.BASE_IP, image); return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer() { @Override diff --git a/app/build.gradle b/app/build.gradle index f98f5bc..9d60011 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,4 +56,10 @@ implementation 'com.google.code.gson:gson:2.8.6' //ZBar扫一扫 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' + //图片选择框架 + implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.5.0' + //图片压缩框架 + implementation 'top.zibin:Luban:1.1.8' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2b7b378..c6065dc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/QMUI.Compat.NoActionBar" @@ -29,6 +30,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java new file mode 100644 index 0000000..e685c07 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java @@ -0,0 +1,18 @@ +package com.casic.birmm.hxrq.bean; + +/** + * @Author: Pengxh + * @Time: 2021/4/9 19:00 + * @Email: 290677893@qq.com + **/ +public class ImageBean { + private String image; + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java index 06c0332..d8b2ab7 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.model; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.utils.HttpConfig; import com.casic.birmm.hxrq.utils.retrofit.RetrofitServiceManager; @@ -33,7 +34,7 @@ } @Override - public Subscription sendRetrofitRequest(String image) { + public Subscription sendRetrofitRequest(ImageBean image) { Observable observable = RetrofitServiceManager.getFaceResult(HttpConfig.BASE_IP, image); return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer() { @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java index 5a14fee..c63312c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java @@ -1,8 +1,9 @@ package com.casic.birmm.hxrq.mvp.model; +import com.casic.birmm.hxrq.bean.ImageBean; + import rx.Subscription; public interface IFaceLoginModel { - //image传的是图片的base64编码 - Subscription sendRetrofitRequest(String image); + Subscription sendRetrofitRequest(ImageBean image); } diff --git a/app/build.gradle b/app/build.gradle index f98f5bc..9d60011 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,4 +56,10 @@ implementation 'com.google.code.gson:gson:2.8.6' //ZBar扫一扫 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' + //图片选择框架 + implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.5.0' + //图片压缩框架 + implementation 'top.zibin:Luban:1.1.8' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2b7b378..c6065dc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/QMUI.Compat.NoActionBar" @@ -29,6 +30,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java new file mode 100644 index 0000000..e685c07 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java @@ -0,0 +1,18 @@ +package com.casic.birmm.hxrq.bean; + +/** + * @Author: Pengxh + * @Time: 2021/4/9 19:00 + * @Email: 290677893@qq.com + **/ +public class ImageBean { + private String image; + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java index 06c0332..d8b2ab7 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.model; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.utils.HttpConfig; import com.casic.birmm.hxrq.utils.retrofit.RetrofitServiceManager; @@ -33,7 +34,7 @@ } @Override - public Subscription sendRetrofitRequest(String image) { + public Subscription sendRetrofitRequest(ImageBean image) { Observable observable = RetrofitServiceManager.getFaceResult(HttpConfig.BASE_IP, image); return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer() { @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java index 5a14fee..c63312c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java @@ -1,8 +1,9 @@ package com.casic.birmm.hxrq.mvp.model; +import com.casic.birmm.hxrq.bean.ImageBean; + import rx.Subscription; public interface IFaceLoginModel { - //image传的是图片的base64编码 - Subscription sendRetrofitRequest(String image); + Subscription sendRetrofitRequest(ImageBean image); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java index 51e4f4f..7fb154c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.presenter; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.mvp.BasePresenter; import com.casic.birmm.hxrq.mvp.model.FaceLoginModelImpl; import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; @@ -21,7 +22,7 @@ } @Override - public void onReadyRetrofitRequest(String image) { + public void onReadyRetrofitRequest(ImageBean image) { addSubscription(actionModel.sendRetrofitRequest(image)); } @@ -30,6 +31,7 @@ unSubscription(); } + @Override public void onSuccess(FaceLoginResultBean resultBean) { view.obtainFaceLoginData(resultBean); diff --git a/app/build.gradle b/app/build.gradle index f98f5bc..9d60011 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,4 +56,10 @@ implementation 'com.google.code.gson:gson:2.8.6' //ZBar扫一扫 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' + //图片选择框架 + implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.5.0' + //图片压缩框架 + implementation 'top.zibin:Luban:1.1.8' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2b7b378..c6065dc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/QMUI.Compat.NoActionBar" @@ -29,6 +30,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java new file mode 100644 index 0000000..e685c07 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java @@ -0,0 +1,18 @@ +package com.casic.birmm.hxrq.bean; + +/** + * @Author: Pengxh + * @Time: 2021/4/9 19:00 + * @Email: 290677893@qq.com + **/ +public class ImageBean { + private String image; + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java index 06c0332..d8b2ab7 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.model; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.utils.HttpConfig; import com.casic.birmm.hxrq.utils.retrofit.RetrofitServiceManager; @@ -33,7 +34,7 @@ } @Override - public Subscription sendRetrofitRequest(String image) { + public Subscription sendRetrofitRequest(ImageBean image) { Observable observable = RetrofitServiceManager.getFaceResult(HttpConfig.BASE_IP, image); return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer() { @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java index 5a14fee..c63312c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java @@ -1,8 +1,9 @@ package com.casic.birmm.hxrq.mvp.model; +import com.casic.birmm.hxrq.bean.ImageBean; + import rx.Subscription; public interface IFaceLoginModel { - //image传的是图片的base64编码 - Subscription sendRetrofitRequest(String image); + Subscription sendRetrofitRequest(ImageBean image); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java index 51e4f4f..7fb154c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.presenter; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.mvp.BasePresenter; import com.casic.birmm.hxrq.mvp.model.FaceLoginModelImpl; import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; @@ -21,7 +22,7 @@ } @Override - public void onReadyRetrofitRequest(String image) { + public void onReadyRetrofitRequest(ImageBean image) { addSubscription(actionModel.sendRetrofitRequest(image)); } @@ -30,6 +31,7 @@ unSubscription(); } + @Override public void onSuccess(FaceLoginResultBean resultBean) { view.obtainFaceLoginData(resultBean); diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java index f525a45..01a5512 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java @@ -1,12 +1,14 @@ package com.casic.birmm.hxrq.mvp.presenter; +import com.casic.birmm.hxrq.bean.ImageBean; + /** * @Author: Pengxh * @Time: 2021/4/9 14:55 * @Email: 290677893@qq.com **/ public interface IFaceLoginPresenter { - void onReadyRetrofitRequest(String image); + void onReadyRetrofitRequest(ImageBean image); void disposeRetrofitRequest(); } diff --git a/app/build.gradle b/app/build.gradle index f98f5bc..9d60011 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,4 +56,10 @@ implementation 'com.google.code.gson:gson:2.8.6' //ZBar扫一扫 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' + //图片选择框架 + implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.5.0' + //图片压缩框架 + implementation 'top.zibin:Luban:1.1.8' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2b7b378..c6065dc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/QMUI.Compat.NoActionBar" @@ -29,6 +30,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java new file mode 100644 index 0000000..e685c07 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java @@ -0,0 +1,18 @@ +package com.casic.birmm.hxrq.bean; + +/** + * @Author: Pengxh + * @Time: 2021/4/9 19:00 + * @Email: 290677893@qq.com + **/ +public class ImageBean { + private String image; + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java index 06c0332..d8b2ab7 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.model; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.utils.HttpConfig; import com.casic.birmm.hxrq.utils.retrofit.RetrofitServiceManager; @@ -33,7 +34,7 @@ } @Override - public Subscription sendRetrofitRequest(String image) { + public Subscription sendRetrofitRequest(ImageBean image) { Observable observable = RetrofitServiceManager.getFaceResult(HttpConfig.BASE_IP, image); return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer() { @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java index 5a14fee..c63312c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java @@ -1,8 +1,9 @@ package com.casic.birmm.hxrq.mvp.model; +import com.casic.birmm.hxrq.bean.ImageBean; + import rx.Subscription; public interface IFaceLoginModel { - //image传的是图片的base64编码 - Subscription sendRetrofitRequest(String image); + Subscription sendRetrofitRequest(ImageBean image); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java index 51e4f4f..7fb154c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.presenter; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.mvp.BasePresenter; import com.casic.birmm.hxrq.mvp.model.FaceLoginModelImpl; import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; @@ -21,7 +22,7 @@ } @Override - public void onReadyRetrofitRequest(String image) { + public void onReadyRetrofitRequest(ImageBean image) { addSubscription(actionModel.sendRetrofitRequest(image)); } @@ -30,6 +31,7 @@ unSubscription(); } + @Override public void onSuccess(FaceLoginResultBean resultBean) { view.obtainFaceLoginData(resultBean); diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java index f525a45..01a5512 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java @@ -1,12 +1,14 @@ package com.casic.birmm.hxrq.mvp.presenter; +import com.casic.birmm.hxrq.bean.ImageBean; + /** * @Author: Pengxh * @Time: 2021/4/9 14:55 * @Email: 290677893@qq.com **/ public interface IFaceLoginPresenter { - void onReadyRetrofitRequest(String image); + void onReadyRetrofitRequest(ImageBean image); void disposeRetrofitRequest(); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java index e9f01ce..98aef9d 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java @@ -9,12 +9,14 @@ import android.view.View; import android.widget.CheckBox; import android.widget.EditText; -import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.Nullable; + import com.casic.birmm.hxrq.R; import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.bean.LoginResultBean; import com.casic.birmm.hxrq.bean.PublicKeyBean; import com.casic.birmm.hxrq.bean.QrCodeBean; @@ -26,14 +28,23 @@ import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; import com.casic.birmm.hxrq.mvp.view.ILoginView; import com.casic.birmm.hxrq.mvp.view.IQrCodeDataView; +import com.casic.birmm.hxrq.utils.FileUtils; +import com.casic.birmm.hxrq.utils.GlideLoadEngine; import com.casic.birmm.hxrq.utils.RSAUtils; import com.casic.birmm.hxrq.utils.SaveKeyValues; +import com.casic.birmm.hxrq.utils.StringHelper; import com.casic.birmm.hxrq.utils.TokenHelper; +import com.google.gson.Gson; +import com.luck.picture.lib.PictureSelector; +import com.luck.picture.lib.config.PictureConfig; +import com.luck.picture.lib.config.PictureMimeType; +import com.luck.picture.lib.entity.LocalMedia; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.dialog.QMUIDialog; import com.qmuiteam.qmui.widget.dialog.QMUITipDialog; import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton; +import java.io.File; import java.security.PublicKey; import butterknife.BindView; @@ -42,6 +53,9 @@ import cn.bertsir.zbar.QrConfig; import cn.bertsir.zbar.QrManager; import cn.bertsir.zbar.view.ScanLineView; +import top.zibin.luban.CompressionPredicate; +import top.zibin.luban.Luban; +import top.zibin.luban.OnCompressListener; public class LoginActivity extends DoubleClickExitActivity implements View.OnClickListener, IAuthenticateView, ILoginView, IQrCodeDataView, IFaceLoginView { @@ -56,8 +70,6 @@ QMUIRoundButton loginButton; @BindView(R.id.rememberPasswordView) CheckBox rememberPasswordView; - @BindView(R.id.changeLoginModeView) - TextView changeLoginModeView; private QMUITipDialog loadingDialog; private AuthenticatePresenterImpl authenticatePresenter; @@ -130,7 +142,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } else { @@ -146,7 +158,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } @@ -156,6 +168,55 @@ } } + private void captureFaceData() { + //TODO 调相机,捕获人脸数据,并保存为文件得到路径 + PictureSelector.create(this) + .openCamera(PictureMimeType.ofImage()) + .imageEngine(GlideLoadEngine.createGlideEngine()) + .maxSelectNum(1) + .forResult(PictureConfig.REQUEST_CAMERA); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + if (requestCode == PictureConfig.REQUEST_CAMERA) { + LocalMedia localMedia = PictureSelector.obtainMultipleResult(data).get(0); + Luban.with(this) + .load(localMedia.getRealPath()) + .ignoreBy(100) + .setTargetDir(FileUtils.getFileDir("CompressImageFile")) + .filter(new CompressionPredicate() { + @Override + public boolean apply(String path) { + return !(TextUtils.isEmpty(path) || path.toLowerCase().endsWith(".gif")); + } + }) + .setCompressListener(new OnCompressListener() { + @Override + public void onStart() { + // TODO 压缩开始前调用,可以在方法内启动 loading UI + } + + @Override + public void onSuccess(File file) { + String imageToBase64 = StringHelper.imageToBase64(file); + + ImageBean imageBean = new ImageBean(); + imageBean.setImage(imageToBase64); + faceLoginPresenter.onReadyRetrofitRequest(imageBean); + } + + @Override + public void onError(Throwable e) { + // TODO 当压缩过程出现问题时调用 + } + }).launch(); + } + } + } + private void startScannerLogin() { QrConfig qrConfig = new QrConfig.Builder() .setTitleText("扫码登录")//设置Title文字 @@ -193,7 +254,7 @@ @Override public void authenticateResult(PublicKeyBean result) { -// Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); + Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); if (result.isSuccess()) { PublicKey publicKey = RSAUtils.keyStrToPublicKey(result.getData().getPublicKey()); if (TextUtils.isEmpty(userName)) { @@ -240,12 +301,22 @@ //验证成功登录 startActivity(new Intent(this, MainActivity.class)); finish(); + } else { + Toast.makeText(this, "二维码已失效", Toast.LENGTH_SHORT).show(); } } @Override public void obtainFaceLoginData(FaceLoginResultBean resultBean) { - +// Log.d(TAG, "obtainFaceLoginData: " + new Gson().toJson(resultBean)); + if (resultBean.getCode() == 200) { + TokenHelper.saveToken(resultBean.getData().getToken()); + //验证成功登录 + startActivity(new Intent(this, MainActivity.class)); + finish(); + } else { + Toast.makeText(this, "无法解析人脸", Toast.LENGTH_SHORT).show(); + } } @Override diff --git a/app/build.gradle b/app/build.gradle index f98f5bc..9d60011 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,4 +56,10 @@ implementation 'com.google.code.gson:gson:2.8.6' //ZBar扫一扫 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' + //图片选择框架 + implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.5.0' + //图片压缩框架 + implementation 'top.zibin:Luban:1.1.8' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2b7b378..c6065dc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/QMUI.Compat.NoActionBar" @@ -29,6 +30,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java new file mode 100644 index 0000000..e685c07 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java @@ -0,0 +1,18 @@ +package com.casic.birmm.hxrq.bean; + +/** + * @Author: Pengxh + * @Time: 2021/4/9 19:00 + * @Email: 290677893@qq.com + **/ +public class ImageBean { + private String image; + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java index 06c0332..d8b2ab7 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.model; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.utils.HttpConfig; import com.casic.birmm.hxrq.utils.retrofit.RetrofitServiceManager; @@ -33,7 +34,7 @@ } @Override - public Subscription sendRetrofitRequest(String image) { + public Subscription sendRetrofitRequest(ImageBean image) { Observable observable = RetrofitServiceManager.getFaceResult(HttpConfig.BASE_IP, image); return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer() { @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java index 5a14fee..c63312c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java @@ -1,8 +1,9 @@ package com.casic.birmm.hxrq.mvp.model; +import com.casic.birmm.hxrq.bean.ImageBean; + import rx.Subscription; public interface IFaceLoginModel { - //image传的是图片的base64编码 - Subscription sendRetrofitRequest(String image); + Subscription sendRetrofitRequest(ImageBean image); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java index 51e4f4f..7fb154c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.presenter; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.mvp.BasePresenter; import com.casic.birmm.hxrq.mvp.model.FaceLoginModelImpl; import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; @@ -21,7 +22,7 @@ } @Override - public void onReadyRetrofitRequest(String image) { + public void onReadyRetrofitRequest(ImageBean image) { addSubscription(actionModel.sendRetrofitRequest(image)); } @@ -30,6 +31,7 @@ unSubscription(); } + @Override public void onSuccess(FaceLoginResultBean resultBean) { view.obtainFaceLoginData(resultBean); diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java index f525a45..01a5512 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java @@ -1,12 +1,14 @@ package com.casic.birmm.hxrq.mvp.presenter; +import com.casic.birmm.hxrq.bean.ImageBean; + /** * @Author: Pengxh * @Time: 2021/4/9 14:55 * @Email: 290677893@qq.com **/ public interface IFaceLoginPresenter { - void onReadyRetrofitRequest(String image); + void onReadyRetrofitRequest(ImageBean image); void disposeRetrofitRequest(); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java index e9f01ce..98aef9d 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java @@ -9,12 +9,14 @@ import android.view.View; import android.widget.CheckBox; import android.widget.EditText; -import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.Nullable; + import com.casic.birmm.hxrq.R; import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.bean.LoginResultBean; import com.casic.birmm.hxrq.bean.PublicKeyBean; import com.casic.birmm.hxrq.bean.QrCodeBean; @@ -26,14 +28,23 @@ import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; import com.casic.birmm.hxrq.mvp.view.ILoginView; import com.casic.birmm.hxrq.mvp.view.IQrCodeDataView; +import com.casic.birmm.hxrq.utils.FileUtils; +import com.casic.birmm.hxrq.utils.GlideLoadEngine; import com.casic.birmm.hxrq.utils.RSAUtils; import com.casic.birmm.hxrq.utils.SaveKeyValues; +import com.casic.birmm.hxrq.utils.StringHelper; import com.casic.birmm.hxrq.utils.TokenHelper; +import com.google.gson.Gson; +import com.luck.picture.lib.PictureSelector; +import com.luck.picture.lib.config.PictureConfig; +import com.luck.picture.lib.config.PictureMimeType; +import com.luck.picture.lib.entity.LocalMedia; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.dialog.QMUIDialog; import com.qmuiteam.qmui.widget.dialog.QMUITipDialog; import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton; +import java.io.File; import java.security.PublicKey; import butterknife.BindView; @@ -42,6 +53,9 @@ import cn.bertsir.zbar.QrConfig; import cn.bertsir.zbar.QrManager; import cn.bertsir.zbar.view.ScanLineView; +import top.zibin.luban.CompressionPredicate; +import top.zibin.luban.Luban; +import top.zibin.luban.OnCompressListener; public class LoginActivity extends DoubleClickExitActivity implements View.OnClickListener, IAuthenticateView, ILoginView, IQrCodeDataView, IFaceLoginView { @@ -56,8 +70,6 @@ QMUIRoundButton loginButton; @BindView(R.id.rememberPasswordView) CheckBox rememberPasswordView; - @BindView(R.id.changeLoginModeView) - TextView changeLoginModeView; private QMUITipDialog loadingDialog; private AuthenticatePresenterImpl authenticatePresenter; @@ -130,7 +142,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } else { @@ -146,7 +158,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } @@ -156,6 +168,55 @@ } } + private void captureFaceData() { + //TODO 调相机,捕获人脸数据,并保存为文件得到路径 + PictureSelector.create(this) + .openCamera(PictureMimeType.ofImage()) + .imageEngine(GlideLoadEngine.createGlideEngine()) + .maxSelectNum(1) + .forResult(PictureConfig.REQUEST_CAMERA); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + if (requestCode == PictureConfig.REQUEST_CAMERA) { + LocalMedia localMedia = PictureSelector.obtainMultipleResult(data).get(0); + Luban.with(this) + .load(localMedia.getRealPath()) + .ignoreBy(100) + .setTargetDir(FileUtils.getFileDir("CompressImageFile")) + .filter(new CompressionPredicate() { + @Override + public boolean apply(String path) { + return !(TextUtils.isEmpty(path) || path.toLowerCase().endsWith(".gif")); + } + }) + .setCompressListener(new OnCompressListener() { + @Override + public void onStart() { + // TODO 压缩开始前调用,可以在方法内启动 loading UI + } + + @Override + public void onSuccess(File file) { + String imageToBase64 = StringHelper.imageToBase64(file); + + ImageBean imageBean = new ImageBean(); + imageBean.setImage(imageToBase64); + faceLoginPresenter.onReadyRetrofitRequest(imageBean); + } + + @Override + public void onError(Throwable e) { + // TODO 当压缩过程出现问题时调用 + } + }).launch(); + } + } + } + private void startScannerLogin() { QrConfig qrConfig = new QrConfig.Builder() .setTitleText("扫码登录")//设置Title文字 @@ -193,7 +254,7 @@ @Override public void authenticateResult(PublicKeyBean result) { -// Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); + Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); if (result.isSuccess()) { PublicKey publicKey = RSAUtils.keyStrToPublicKey(result.getData().getPublicKey()); if (TextUtils.isEmpty(userName)) { @@ -240,12 +301,22 @@ //验证成功登录 startActivity(new Intent(this, MainActivity.class)); finish(); + } else { + Toast.makeText(this, "二维码已失效", Toast.LENGTH_SHORT).show(); } } @Override public void obtainFaceLoginData(FaceLoginResultBean resultBean) { - +// Log.d(TAG, "obtainFaceLoginData: " + new Gson().toJson(resultBean)); + if (resultBean.getCode() == 200) { + TokenHelper.saveToken(resultBean.getData().getToken()); + //验证成功登录 + startActivity(new Intent(this, MainActivity.class)); + finish(); + } else { + Toast.makeText(this, "无法解析人脸", Toast.LENGTH_SHORT).show(); + } } @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java index 4baf176..f70848a 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java @@ -3,14 +3,14 @@ import androidx.core.content.ContextCompat; import com.casic.birmm.hxrq.R; -import com.casic.birmm.hxrq.base.BaseActivity; +import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.utils.SaveKeyValues; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.QMUITopBarLayout; import butterknife.BindView; -public class MainActivity extends BaseActivity { +public class MainActivity extends DoubleClickExitActivity { @BindView(R.id.mainTopLayout) QMUITopBarLayout mainTopLayout; diff --git a/app/build.gradle b/app/build.gradle index f98f5bc..9d60011 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,4 +56,10 @@ implementation 'com.google.code.gson:gson:2.8.6' //ZBar扫一扫 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' + //图片选择框架 + implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.5.0' + //图片压缩框架 + implementation 'top.zibin:Luban:1.1.8' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2b7b378..c6065dc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/QMUI.Compat.NoActionBar" @@ -29,6 +30,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java new file mode 100644 index 0000000..e685c07 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java @@ -0,0 +1,18 @@ +package com.casic.birmm.hxrq.bean; + +/** + * @Author: Pengxh + * @Time: 2021/4/9 19:00 + * @Email: 290677893@qq.com + **/ +public class ImageBean { + private String image; + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java index 06c0332..d8b2ab7 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.model; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.utils.HttpConfig; import com.casic.birmm.hxrq.utils.retrofit.RetrofitServiceManager; @@ -33,7 +34,7 @@ } @Override - public Subscription sendRetrofitRequest(String image) { + public Subscription sendRetrofitRequest(ImageBean image) { Observable observable = RetrofitServiceManager.getFaceResult(HttpConfig.BASE_IP, image); return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer() { @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java index 5a14fee..c63312c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java @@ -1,8 +1,9 @@ package com.casic.birmm.hxrq.mvp.model; +import com.casic.birmm.hxrq.bean.ImageBean; + import rx.Subscription; public interface IFaceLoginModel { - //image传的是图片的base64编码 - Subscription sendRetrofitRequest(String image); + Subscription sendRetrofitRequest(ImageBean image); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java index 51e4f4f..7fb154c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.presenter; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.mvp.BasePresenter; import com.casic.birmm.hxrq.mvp.model.FaceLoginModelImpl; import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; @@ -21,7 +22,7 @@ } @Override - public void onReadyRetrofitRequest(String image) { + public void onReadyRetrofitRequest(ImageBean image) { addSubscription(actionModel.sendRetrofitRequest(image)); } @@ -30,6 +31,7 @@ unSubscription(); } + @Override public void onSuccess(FaceLoginResultBean resultBean) { view.obtainFaceLoginData(resultBean); diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java index f525a45..01a5512 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java @@ -1,12 +1,14 @@ package com.casic.birmm.hxrq.mvp.presenter; +import com.casic.birmm.hxrq.bean.ImageBean; + /** * @Author: Pengxh * @Time: 2021/4/9 14:55 * @Email: 290677893@qq.com **/ public interface IFaceLoginPresenter { - void onReadyRetrofitRequest(String image); + void onReadyRetrofitRequest(ImageBean image); void disposeRetrofitRequest(); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java index e9f01ce..98aef9d 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java @@ -9,12 +9,14 @@ import android.view.View; import android.widget.CheckBox; import android.widget.EditText; -import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.Nullable; + import com.casic.birmm.hxrq.R; import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.bean.LoginResultBean; import com.casic.birmm.hxrq.bean.PublicKeyBean; import com.casic.birmm.hxrq.bean.QrCodeBean; @@ -26,14 +28,23 @@ import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; import com.casic.birmm.hxrq.mvp.view.ILoginView; import com.casic.birmm.hxrq.mvp.view.IQrCodeDataView; +import com.casic.birmm.hxrq.utils.FileUtils; +import com.casic.birmm.hxrq.utils.GlideLoadEngine; import com.casic.birmm.hxrq.utils.RSAUtils; import com.casic.birmm.hxrq.utils.SaveKeyValues; +import com.casic.birmm.hxrq.utils.StringHelper; import com.casic.birmm.hxrq.utils.TokenHelper; +import com.google.gson.Gson; +import com.luck.picture.lib.PictureSelector; +import com.luck.picture.lib.config.PictureConfig; +import com.luck.picture.lib.config.PictureMimeType; +import com.luck.picture.lib.entity.LocalMedia; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.dialog.QMUIDialog; import com.qmuiteam.qmui.widget.dialog.QMUITipDialog; import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton; +import java.io.File; import java.security.PublicKey; import butterknife.BindView; @@ -42,6 +53,9 @@ import cn.bertsir.zbar.QrConfig; import cn.bertsir.zbar.QrManager; import cn.bertsir.zbar.view.ScanLineView; +import top.zibin.luban.CompressionPredicate; +import top.zibin.luban.Luban; +import top.zibin.luban.OnCompressListener; public class LoginActivity extends DoubleClickExitActivity implements View.OnClickListener, IAuthenticateView, ILoginView, IQrCodeDataView, IFaceLoginView { @@ -56,8 +70,6 @@ QMUIRoundButton loginButton; @BindView(R.id.rememberPasswordView) CheckBox rememberPasswordView; - @BindView(R.id.changeLoginModeView) - TextView changeLoginModeView; private QMUITipDialog loadingDialog; private AuthenticatePresenterImpl authenticatePresenter; @@ -130,7 +142,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } else { @@ -146,7 +158,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } @@ -156,6 +168,55 @@ } } + private void captureFaceData() { + //TODO 调相机,捕获人脸数据,并保存为文件得到路径 + PictureSelector.create(this) + .openCamera(PictureMimeType.ofImage()) + .imageEngine(GlideLoadEngine.createGlideEngine()) + .maxSelectNum(1) + .forResult(PictureConfig.REQUEST_CAMERA); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + if (requestCode == PictureConfig.REQUEST_CAMERA) { + LocalMedia localMedia = PictureSelector.obtainMultipleResult(data).get(0); + Luban.with(this) + .load(localMedia.getRealPath()) + .ignoreBy(100) + .setTargetDir(FileUtils.getFileDir("CompressImageFile")) + .filter(new CompressionPredicate() { + @Override + public boolean apply(String path) { + return !(TextUtils.isEmpty(path) || path.toLowerCase().endsWith(".gif")); + } + }) + .setCompressListener(new OnCompressListener() { + @Override + public void onStart() { + // TODO 压缩开始前调用,可以在方法内启动 loading UI + } + + @Override + public void onSuccess(File file) { + String imageToBase64 = StringHelper.imageToBase64(file); + + ImageBean imageBean = new ImageBean(); + imageBean.setImage(imageToBase64); + faceLoginPresenter.onReadyRetrofitRequest(imageBean); + } + + @Override + public void onError(Throwable e) { + // TODO 当压缩过程出现问题时调用 + } + }).launch(); + } + } + } + private void startScannerLogin() { QrConfig qrConfig = new QrConfig.Builder() .setTitleText("扫码登录")//设置Title文字 @@ -193,7 +254,7 @@ @Override public void authenticateResult(PublicKeyBean result) { -// Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); + Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); if (result.isSuccess()) { PublicKey publicKey = RSAUtils.keyStrToPublicKey(result.getData().getPublicKey()); if (TextUtils.isEmpty(userName)) { @@ -240,12 +301,22 @@ //验证成功登录 startActivity(new Intent(this, MainActivity.class)); finish(); + } else { + Toast.makeText(this, "二维码已失效", Toast.LENGTH_SHORT).show(); } } @Override public void obtainFaceLoginData(FaceLoginResultBean resultBean) { - +// Log.d(TAG, "obtainFaceLoginData: " + new Gson().toJson(resultBean)); + if (resultBean.getCode() == 200) { + TokenHelper.saveToken(resultBean.getData().getToken()); + //验证成功登录 + startActivity(new Intent(this, MainActivity.class)); + finish(); + } else { + Toast.makeText(this, "无法解析人脸", Toast.LENGTH_SHORT).show(); + } } @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java index 4baf176..f70848a 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java @@ -3,14 +3,14 @@ import androidx.core.content.ContextCompat; import com.casic.birmm.hxrq.R; -import com.casic.birmm.hxrq.base.BaseActivity; +import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.utils.SaveKeyValues; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.QMUITopBarLayout; import butterknife.BindView; -public class MainActivity extends BaseActivity { +public class MainActivity extends DoubleClickExitActivity { @BindView(R.id.mainTopLayout) QMUITopBarLayout mainTopLayout; diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java b/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java new file mode 100644 index 0000000..fc939a7 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java @@ -0,0 +1,34 @@ +package com.casic.birmm.hxrq.utils; + +import android.os.Environment; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +public class FileUtils { + + public static String getFileDir(String dirName) { + File imageDir = new File(Environment.getExternalStorageDirectory(), dirName); + if (!imageDir.exists()) { + imageDir.mkdir(); + } + return imageDir.toString(); + } + + public static File getFaceImageFile() { + String imageDir = getFileDir("FaceImageFile"); + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date()); + File imageFile = new File(imageDir + File.separator + "IMG_" + timeStamp + ".png"); + if (!imageFile.exists()) { + try { + imageFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return imageFile; + } +} diff --git a/app/build.gradle b/app/build.gradle index f98f5bc..9d60011 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,4 +56,10 @@ implementation 'com.google.code.gson:gson:2.8.6' //ZBar扫一扫 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' + //图片选择框架 + implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.5.0' + //图片压缩框架 + implementation 'top.zibin:Luban:1.1.8' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2b7b378..c6065dc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/QMUI.Compat.NoActionBar" @@ -29,6 +30,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java new file mode 100644 index 0000000..e685c07 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java @@ -0,0 +1,18 @@ +package com.casic.birmm.hxrq.bean; + +/** + * @Author: Pengxh + * @Time: 2021/4/9 19:00 + * @Email: 290677893@qq.com + **/ +public class ImageBean { + private String image; + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java index 06c0332..d8b2ab7 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.model; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.utils.HttpConfig; import com.casic.birmm.hxrq.utils.retrofit.RetrofitServiceManager; @@ -33,7 +34,7 @@ } @Override - public Subscription sendRetrofitRequest(String image) { + public Subscription sendRetrofitRequest(ImageBean image) { Observable observable = RetrofitServiceManager.getFaceResult(HttpConfig.BASE_IP, image); return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer() { @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java index 5a14fee..c63312c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java @@ -1,8 +1,9 @@ package com.casic.birmm.hxrq.mvp.model; +import com.casic.birmm.hxrq.bean.ImageBean; + import rx.Subscription; public interface IFaceLoginModel { - //image传的是图片的base64编码 - Subscription sendRetrofitRequest(String image); + Subscription sendRetrofitRequest(ImageBean image); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java index 51e4f4f..7fb154c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.presenter; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.mvp.BasePresenter; import com.casic.birmm.hxrq.mvp.model.FaceLoginModelImpl; import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; @@ -21,7 +22,7 @@ } @Override - public void onReadyRetrofitRequest(String image) { + public void onReadyRetrofitRequest(ImageBean image) { addSubscription(actionModel.sendRetrofitRequest(image)); } @@ -30,6 +31,7 @@ unSubscription(); } + @Override public void onSuccess(FaceLoginResultBean resultBean) { view.obtainFaceLoginData(resultBean); diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java index f525a45..01a5512 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java @@ -1,12 +1,14 @@ package com.casic.birmm.hxrq.mvp.presenter; +import com.casic.birmm.hxrq.bean.ImageBean; + /** * @Author: Pengxh * @Time: 2021/4/9 14:55 * @Email: 290677893@qq.com **/ public interface IFaceLoginPresenter { - void onReadyRetrofitRequest(String image); + void onReadyRetrofitRequest(ImageBean image); void disposeRetrofitRequest(); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java index e9f01ce..98aef9d 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java @@ -9,12 +9,14 @@ import android.view.View; import android.widget.CheckBox; import android.widget.EditText; -import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.Nullable; + import com.casic.birmm.hxrq.R; import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.bean.LoginResultBean; import com.casic.birmm.hxrq.bean.PublicKeyBean; import com.casic.birmm.hxrq.bean.QrCodeBean; @@ -26,14 +28,23 @@ import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; import com.casic.birmm.hxrq.mvp.view.ILoginView; import com.casic.birmm.hxrq.mvp.view.IQrCodeDataView; +import com.casic.birmm.hxrq.utils.FileUtils; +import com.casic.birmm.hxrq.utils.GlideLoadEngine; import com.casic.birmm.hxrq.utils.RSAUtils; import com.casic.birmm.hxrq.utils.SaveKeyValues; +import com.casic.birmm.hxrq.utils.StringHelper; import com.casic.birmm.hxrq.utils.TokenHelper; +import com.google.gson.Gson; +import com.luck.picture.lib.PictureSelector; +import com.luck.picture.lib.config.PictureConfig; +import com.luck.picture.lib.config.PictureMimeType; +import com.luck.picture.lib.entity.LocalMedia; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.dialog.QMUIDialog; import com.qmuiteam.qmui.widget.dialog.QMUITipDialog; import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton; +import java.io.File; import java.security.PublicKey; import butterknife.BindView; @@ -42,6 +53,9 @@ import cn.bertsir.zbar.QrConfig; import cn.bertsir.zbar.QrManager; import cn.bertsir.zbar.view.ScanLineView; +import top.zibin.luban.CompressionPredicate; +import top.zibin.luban.Luban; +import top.zibin.luban.OnCompressListener; public class LoginActivity extends DoubleClickExitActivity implements View.OnClickListener, IAuthenticateView, ILoginView, IQrCodeDataView, IFaceLoginView { @@ -56,8 +70,6 @@ QMUIRoundButton loginButton; @BindView(R.id.rememberPasswordView) CheckBox rememberPasswordView; - @BindView(R.id.changeLoginModeView) - TextView changeLoginModeView; private QMUITipDialog loadingDialog; private AuthenticatePresenterImpl authenticatePresenter; @@ -130,7 +142,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } else { @@ -146,7 +158,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } @@ -156,6 +168,55 @@ } } + private void captureFaceData() { + //TODO 调相机,捕获人脸数据,并保存为文件得到路径 + PictureSelector.create(this) + .openCamera(PictureMimeType.ofImage()) + .imageEngine(GlideLoadEngine.createGlideEngine()) + .maxSelectNum(1) + .forResult(PictureConfig.REQUEST_CAMERA); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + if (requestCode == PictureConfig.REQUEST_CAMERA) { + LocalMedia localMedia = PictureSelector.obtainMultipleResult(data).get(0); + Luban.with(this) + .load(localMedia.getRealPath()) + .ignoreBy(100) + .setTargetDir(FileUtils.getFileDir("CompressImageFile")) + .filter(new CompressionPredicate() { + @Override + public boolean apply(String path) { + return !(TextUtils.isEmpty(path) || path.toLowerCase().endsWith(".gif")); + } + }) + .setCompressListener(new OnCompressListener() { + @Override + public void onStart() { + // TODO 压缩开始前调用,可以在方法内启动 loading UI + } + + @Override + public void onSuccess(File file) { + String imageToBase64 = StringHelper.imageToBase64(file); + + ImageBean imageBean = new ImageBean(); + imageBean.setImage(imageToBase64); + faceLoginPresenter.onReadyRetrofitRequest(imageBean); + } + + @Override + public void onError(Throwable e) { + // TODO 当压缩过程出现问题时调用 + } + }).launch(); + } + } + } + private void startScannerLogin() { QrConfig qrConfig = new QrConfig.Builder() .setTitleText("扫码登录")//设置Title文字 @@ -193,7 +254,7 @@ @Override public void authenticateResult(PublicKeyBean result) { -// Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); + Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); if (result.isSuccess()) { PublicKey publicKey = RSAUtils.keyStrToPublicKey(result.getData().getPublicKey()); if (TextUtils.isEmpty(userName)) { @@ -240,12 +301,22 @@ //验证成功登录 startActivity(new Intent(this, MainActivity.class)); finish(); + } else { + Toast.makeText(this, "二维码已失效", Toast.LENGTH_SHORT).show(); } } @Override public void obtainFaceLoginData(FaceLoginResultBean resultBean) { - +// Log.d(TAG, "obtainFaceLoginData: " + new Gson().toJson(resultBean)); + if (resultBean.getCode() == 200) { + TokenHelper.saveToken(resultBean.getData().getToken()); + //验证成功登录 + startActivity(new Intent(this, MainActivity.class)); + finish(); + } else { + Toast.makeText(this, "无法解析人脸", Toast.LENGTH_SHORT).show(); + } } @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java index 4baf176..f70848a 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java @@ -3,14 +3,14 @@ import androidx.core.content.ContextCompat; import com.casic.birmm.hxrq.R; -import com.casic.birmm.hxrq.base.BaseActivity; +import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.utils.SaveKeyValues; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.QMUITopBarLayout; import butterknife.BindView; -public class MainActivity extends BaseActivity { +public class MainActivity extends DoubleClickExitActivity { @BindView(R.id.mainTopLayout) QMUITopBarLayout mainTopLayout; diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java b/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java new file mode 100644 index 0000000..fc939a7 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java @@ -0,0 +1,34 @@ +package com.casic.birmm.hxrq.utils; + +import android.os.Environment; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +public class FileUtils { + + public static String getFileDir(String dirName) { + File imageDir = new File(Environment.getExternalStorageDirectory(), dirName); + if (!imageDir.exists()) { + imageDir.mkdir(); + } + return imageDir.toString(); + } + + public static File getFaceImageFile() { + String imageDir = getFileDir("FaceImageFile"); + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date()); + File imageFile = new File(imageDir + File.separator + "IMG_" + timeStamp + ".png"); + if (!imageFile.exists()) { + try { + imageFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return imageFile; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java b/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java new file mode 100644 index 0000000..6de07df --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java @@ -0,0 +1,89 @@ +package com.casic.birmm.hxrq.utils; + +import android.content.Context; +import android.graphics.Bitmap; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.core.graphics.drawable.RoundedBitmapDrawable; +import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; +import com.bumptech.glide.request.target.BitmapImageViewTarget; +import com.casic.birmm.hxrq.R; +import com.luck.picture.lib.engine.ImageEngine; +import com.luck.picture.lib.listener.OnImageCompleteCallback; +import com.luck.picture.lib.widget.longimage.SubsamplingScaleImageView; + +/** + * @Author: Pengxh + * @Time: 2021/4/7 15:54 + * @Emain: 290677893@qq.com + **/ +public class GlideLoadEngine implements ImageEngine { + + private GlideLoadEngine() { + + } + + private static GlideLoadEngine instance; + + public static GlideLoadEngine createGlideEngine() { + if (null == instance) { + synchronized (GlideLoadEngine.class) { + if (null == instance) { + instance = new GlideLoadEngine(); + } + } + } + return instance; + } + + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context).load(url).into(imageView); + } + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView, SubsamplingScaleImageView longImageView, OnImageCompleteCallback callback) { + + } + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView, SubsamplingScaleImageView longImageView) { + + } + + @Override + public void loadFolderImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context) + .asBitmap() + .load(url) + .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder)) + .into(new BitmapImageViewTarget(imageView) { + @Override + protected void setResource(Bitmap resource) { + RoundedBitmapDrawable circularBitmapDrawable = + RoundedBitmapDrawableFactory. + create(context.getResources(), resource); + circularBitmapDrawable.setCornerRadius(8); + imageView.setImageDrawable(circularBitmapDrawable); + } + }); + } + + @Override + public void loadAsGifImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context).asGif().load(url).into(imageView); + } + + @Override + public void loadGridImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context) + .load(url) + .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder)) + .into(imageView); + } +} diff --git a/app/build.gradle b/app/build.gradle index f98f5bc..9d60011 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,4 +56,10 @@ implementation 'com.google.code.gson:gson:2.8.6' //ZBar扫一扫 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' + //图片选择框架 + implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.5.0' + //图片压缩框架 + implementation 'top.zibin:Luban:1.1.8' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2b7b378..c6065dc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/QMUI.Compat.NoActionBar" @@ -29,6 +30,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java new file mode 100644 index 0000000..e685c07 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java @@ -0,0 +1,18 @@ +package com.casic.birmm.hxrq.bean; + +/** + * @Author: Pengxh + * @Time: 2021/4/9 19:00 + * @Email: 290677893@qq.com + **/ +public class ImageBean { + private String image; + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java index 06c0332..d8b2ab7 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.model; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.utils.HttpConfig; import com.casic.birmm.hxrq.utils.retrofit.RetrofitServiceManager; @@ -33,7 +34,7 @@ } @Override - public Subscription sendRetrofitRequest(String image) { + public Subscription sendRetrofitRequest(ImageBean image) { Observable observable = RetrofitServiceManager.getFaceResult(HttpConfig.BASE_IP, image); return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer() { @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java index 5a14fee..c63312c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java @@ -1,8 +1,9 @@ package com.casic.birmm.hxrq.mvp.model; +import com.casic.birmm.hxrq.bean.ImageBean; + import rx.Subscription; public interface IFaceLoginModel { - //image传的是图片的base64编码 - Subscription sendRetrofitRequest(String image); + Subscription sendRetrofitRequest(ImageBean image); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java index 51e4f4f..7fb154c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.presenter; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.mvp.BasePresenter; import com.casic.birmm.hxrq.mvp.model.FaceLoginModelImpl; import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; @@ -21,7 +22,7 @@ } @Override - public void onReadyRetrofitRequest(String image) { + public void onReadyRetrofitRequest(ImageBean image) { addSubscription(actionModel.sendRetrofitRequest(image)); } @@ -30,6 +31,7 @@ unSubscription(); } + @Override public void onSuccess(FaceLoginResultBean resultBean) { view.obtainFaceLoginData(resultBean); diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java index f525a45..01a5512 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java @@ -1,12 +1,14 @@ package com.casic.birmm.hxrq.mvp.presenter; +import com.casic.birmm.hxrq.bean.ImageBean; + /** * @Author: Pengxh * @Time: 2021/4/9 14:55 * @Email: 290677893@qq.com **/ public interface IFaceLoginPresenter { - void onReadyRetrofitRequest(String image); + void onReadyRetrofitRequest(ImageBean image); void disposeRetrofitRequest(); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java index e9f01ce..98aef9d 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java @@ -9,12 +9,14 @@ import android.view.View; import android.widget.CheckBox; import android.widget.EditText; -import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.Nullable; + import com.casic.birmm.hxrq.R; import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.bean.LoginResultBean; import com.casic.birmm.hxrq.bean.PublicKeyBean; import com.casic.birmm.hxrq.bean.QrCodeBean; @@ -26,14 +28,23 @@ import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; import com.casic.birmm.hxrq.mvp.view.ILoginView; import com.casic.birmm.hxrq.mvp.view.IQrCodeDataView; +import com.casic.birmm.hxrq.utils.FileUtils; +import com.casic.birmm.hxrq.utils.GlideLoadEngine; import com.casic.birmm.hxrq.utils.RSAUtils; import com.casic.birmm.hxrq.utils.SaveKeyValues; +import com.casic.birmm.hxrq.utils.StringHelper; import com.casic.birmm.hxrq.utils.TokenHelper; +import com.google.gson.Gson; +import com.luck.picture.lib.PictureSelector; +import com.luck.picture.lib.config.PictureConfig; +import com.luck.picture.lib.config.PictureMimeType; +import com.luck.picture.lib.entity.LocalMedia; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.dialog.QMUIDialog; import com.qmuiteam.qmui.widget.dialog.QMUITipDialog; import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton; +import java.io.File; import java.security.PublicKey; import butterknife.BindView; @@ -42,6 +53,9 @@ import cn.bertsir.zbar.QrConfig; import cn.bertsir.zbar.QrManager; import cn.bertsir.zbar.view.ScanLineView; +import top.zibin.luban.CompressionPredicate; +import top.zibin.luban.Luban; +import top.zibin.luban.OnCompressListener; public class LoginActivity extends DoubleClickExitActivity implements View.OnClickListener, IAuthenticateView, ILoginView, IQrCodeDataView, IFaceLoginView { @@ -56,8 +70,6 @@ QMUIRoundButton loginButton; @BindView(R.id.rememberPasswordView) CheckBox rememberPasswordView; - @BindView(R.id.changeLoginModeView) - TextView changeLoginModeView; private QMUITipDialog loadingDialog; private AuthenticatePresenterImpl authenticatePresenter; @@ -130,7 +142,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } else { @@ -146,7 +158,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } @@ -156,6 +168,55 @@ } } + private void captureFaceData() { + //TODO 调相机,捕获人脸数据,并保存为文件得到路径 + PictureSelector.create(this) + .openCamera(PictureMimeType.ofImage()) + .imageEngine(GlideLoadEngine.createGlideEngine()) + .maxSelectNum(1) + .forResult(PictureConfig.REQUEST_CAMERA); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + if (requestCode == PictureConfig.REQUEST_CAMERA) { + LocalMedia localMedia = PictureSelector.obtainMultipleResult(data).get(0); + Luban.with(this) + .load(localMedia.getRealPath()) + .ignoreBy(100) + .setTargetDir(FileUtils.getFileDir("CompressImageFile")) + .filter(new CompressionPredicate() { + @Override + public boolean apply(String path) { + return !(TextUtils.isEmpty(path) || path.toLowerCase().endsWith(".gif")); + } + }) + .setCompressListener(new OnCompressListener() { + @Override + public void onStart() { + // TODO 压缩开始前调用,可以在方法内启动 loading UI + } + + @Override + public void onSuccess(File file) { + String imageToBase64 = StringHelper.imageToBase64(file); + + ImageBean imageBean = new ImageBean(); + imageBean.setImage(imageToBase64); + faceLoginPresenter.onReadyRetrofitRequest(imageBean); + } + + @Override + public void onError(Throwable e) { + // TODO 当压缩过程出现问题时调用 + } + }).launch(); + } + } + } + private void startScannerLogin() { QrConfig qrConfig = new QrConfig.Builder() .setTitleText("扫码登录")//设置Title文字 @@ -193,7 +254,7 @@ @Override public void authenticateResult(PublicKeyBean result) { -// Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); + Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); if (result.isSuccess()) { PublicKey publicKey = RSAUtils.keyStrToPublicKey(result.getData().getPublicKey()); if (TextUtils.isEmpty(userName)) { @@ -240,12 +301,22 @@ //验证成功登录 startActivity(new Intent(this, MainActivity.class)); finish(); + } else { + Toast.makeText(this, "二维码已失效", Toast.LENGTH_SHORT).show(); } } @Override public void obtainFaceLoginData(FaceLoginResultBean resultBean) { - +// Log.d(TAG, "obtainFaceLoginData: " + new Gson().toJson(resultBean)); + if (resultBean.getCode() == 200) { + TokenHelper.saveToken(resultBean.getData().getToken()); + //验证成功登录 + startActivity(new Intent(this, MainActivity.class)); + finish(); + } else { + Toast.makeText(this, "无法解析人脸", Toast.LENGTH_SHORT).show(); + } } @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java index 4baf176..f70848a 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java @@ -3,14 +3,14 @@ import androidx.core.content.ContextCompat; import com.casic.birmm.hxrq.R; -import com.casic.birmm.hxrq.base.BaseActivity; +import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.utils.SaveKeyValues; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.QMUITopBarLayout; import butterknife.BindView; -public class MainActivity extends BaseActivity { +public class MainActivity extends DoubleClickExitActivity { @BindView(R.id.mainTopLayout) QMUITopBarLayout mainTopLayout; diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java b/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java new file mode 100644 index 0000000..fc939a7 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java @@ -0,0 +1,34 @@ +package com.casic.birmm.hxrq.utils; + +import android.os.Environment; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +public class FileUtils { + + public static String getFileDir(String dirName) { + File imageDir = new File(Environment.getExternalStorageDirectory(), dirName); + if (!imageDir.exists()) { + imageDir.mkdir(); + } + return imageDir.toString(); + } + + public static File getFaceImageFile() { + String imageDir = getFileDir("FaceImageFile"); + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date()); + File imageFile = new File(imageDir + File.separator + "IMG_" + timeStamp + ".png"); + if (!imageFile.exists()) { + try { + imageFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return imageFile; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java b/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java new file mode 100644 index 0000000..6de07df --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java @@ -0,0 +1,89 @@ +package com.casic.birmm.hxrq.utils; + +import android.content.Context; +import android.graphics.Bitmap; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.core.graphics.drawable.RoundedBitmapDrawable; +import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; +import com.bumptech.glide.request.target.BitmapImageViewTarget; +import com.casic.birmm.hxrq.R; +import com.luck.picture.lib.engine.ImageEngine; +import com.luck.picture.lib.listener.OnImageCompleteCallback; +import com.luck.picture.lib.widget.longimage.SubsamplingScaleImageView; + +/** + * @Author: Pengxh + * @Time: 2021/4/7 15:54 + * @Emain: 290677893@qq.com + **/ +public class GlideLoadEngine implements ImageEngine { + + private GlideLoadEngine() { + + } + + private static GlideLoadEngine instance; + + public static GlideLoadEngine createGlideEngine() { + if (null == instance) { + synchronized (GlideLoadEngine.class) { + if (null == instance) { + instance = new GlideLoadEngine(); + } + } + } + return instance; + } + + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context).load(url).into(imageView); + } + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView, SubsamplingScaleImageView longImageView, OnImageCompleteCallback callback) { + + } + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView, SubsamplingScaleImageView longImageView) { + + } + + @Override + public void loadFolderImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context) + .asBitmap() + .load(url) + .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder)) + .into(new BitmapImageViewTarget(imageView) { + @Override + protected void setResource(Bitmap resource) { + RoundedBitmapDrawable circularBitmapDrawable = + RoundedBitmapDrawableFactory. + create(context.getResources(), resource); + circularBitmapDrawable.setCornerRadius(8); + imageView.setImageDrawable(circularBitmapDrawable); + } + }); + } + + @Override + public void loadAsGifImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context).asGif().load(url).into(imageView); + } + + @Override + public void loadGridImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context) + .load(url) + .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder)) + .into(imageView); + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java b/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java deleted file mode 100644 index 065eab3..0000000 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.casic.birmm.hxrq.utils; - -import android.util.Log; - -import com.casic.birmm.hxrq.utils.callback.ILoginResultListener; - -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; - -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import rx.Observable; -import rx.Subscriber; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; - -public class HttpHelper { - private static final String TAG = "HttpHelper"; - - public static void loginWithPassword(String url, String userName, String password, ILoginResultListener listener) { - Observable.create((Observable.OnSubscribe) subscriber -> - new OkHttpClient().newCall(new Request.Builder() - .url("http://111.198.10.15:20403/cockpit/mrg/login/") - .get() - .build()) - .enqueue(new Callback() { - @Override - public void onFailure(@NotNull Call call, @NotNull IOException e) { - subscriber.onError(e); - } - - @Override - public void onResponse(@NotNull Call call, @NotNull Response response) { - subscriber.onNext(response); - } - })).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber() { - @Override - public void onError(Throwable e) { - Log.d(TAG, "onError: " + e); - } - - @Override - public void onNext(Response response) { - if (response == null) { - Log.e(TAG, "请求出错: ", new NullPointerException()); - return; - } - try { - Log.d(TAG, "onNext: " + response.body().string()); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void onCompleted() { - Log.d(TAG, "onCompleted: 请求完成"); - } - }); - } -} diff --git a/app/build.gradle b/app/build.gradle index f98f5bc..9d60011 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,4 +56,10 @@ implementation 'com.google.code.gson:gson:2.8.6' //ZBar扫一扫 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' + //图片选择框架 + implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.5.0' + //图片压缩框架 + implementation 'top.zibin:Luban:1.1.8' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2b7b378..c6065dc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/QMUI.Compat.NoActionBar" @@ -29,6 +30,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java new file mode 100644 index 0000000..e685c07 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java @@ -0,0 +1,18 @@ +package com.casic.birmm.hxrq.bean; + +/** + * @Author: Pengxh + * @Time: 2021/4/9 19:00 + * @Email: 290677893@qq.com + **/ +public class ImageBean { + private String image; + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java index 06c0332..d8b2ab7 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.model; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.utils.HttpConfig; import com.casic.birmm.hxrq.utils.retrofit.RetrofitServiceManager; @@ -33,7 +34,7 @@ } @Override - public Subscription sendRetrofitRequest(String image) { + public Subscription sendRetrofitRequest(ImageBean image) { Observable observable = RetrofitServiceManager.getFaceResult(HttpConfig.BASE_IP, image); return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer() { @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java index 5a14fee..c63312c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java @@ -1,8 +1,9 @@ package com.casic.birmm.hxrq.mvp.model; +import com.casic.birmm.hxrq.bean.ImageBean; + import rx.Subscription; public interface IFaceLoginModel { - //image传的是图片的base64编码 - Subscription sendRetrofitRequest(String image); + Subscription sendRetrofitRequest(ImageBean image); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java index 51e4f4f..7fb154c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.presenter; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.mvp.BasePresenter; import com.casic.birmm.hxrq.mvp.model.FaceLoginModelImpl; import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; @@ -21,7 +22,7 @@ } @Override - public void onReadyRetrofitRequest(String image) { + public void onReadyRetrofitRequest(ImageBean image) { addSubscription(actionModel.sendRetrofitRequest(image)); } @@ -30,6 +31,7 @@ unSubscription(); } + @Override public void onSuccess(FaceLoginResultBean resultBean) { view.obtainFaceLoginData(resultBean); diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java index f525a45..01a5512 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java @@ -1,12 +1,14 @@ package com.casic.birmm.hxrq.mvp.presenter; +import com.casic.birmm.hxrq.bean.ImageBean; + /** * @Author: Pengxh * @Time: 2021/4/9 14:55 * @Email: 290677893@qq.com **/ public interface IFaceLoginPresenter { - void onReadyRetrofitRequest(String image); + void onReadyRetrofitRequest(ImageBean image); void disposeRetrofitRequest(); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java index e9f01ce..98aef9d 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java @@ -9,12 +9,14 @@ import android.view.View; import android.widget.CheckBox; import android.widget.EditText; -import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.Nullable; + import com.casic.birmm.hxrq.R; import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.bean.LoginResultBean; import com.casic.birmm.hxrq.bean.PublicKeyBean; import com.casic.birmm.hxrq.bean.QrCodeBean; @@ -26,14 +28,23 @@ import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; import com.casic.birmm.hxrq.mvp.view.ILoginView; import com.casic.birmm.hxrq.mvp.view.IQrCodeDataView; +import com.casic.birmm.hxrq.utils.FileUtils; +import com.casic.birmm.hxrq.utils.GlideLoadEngine; import com.casic.birmm.hxrq.utils.RSAUtils; import com.casic.birmm.hxrq.utils.SaveKeyValues; +import com.casic.birmm.hxrq.utils.StringHelper; import com.casic.birmm.hxrq.utils.TokenHelper; +import com.google.gson.Gson; +import com.luck.picture.lib.PictureSelector; +import com.luck.picture.lib.config.PictureConfig; +import com.luck.picture.lib.config.PictureMimeType; +import com.luck.picture.lib.entity.LocalMedia; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.dialog.QMUIDialog; import com.qmuiteam.qmui.widget.dialog.QMUITipDialog; import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton; +import java.io.File; import java.security.PublicKey; import butterknife.BindView; @@ -42,6 +53,9 @@ import cn.bertsir.zbar.QrConfig; import cn.bertsir.zbar.QrManager; import cn.bertsir.zbar.view.ScanLineView; +import top.zibin.luban.CompressionPredicate; +import top.zibin.luban.Luban; +import top.zibin.luban.OnCompressListener; public class LoginActivity extends DoubleClickExitActivity implements View.OnClickListener, IAuthenticateView, ILoginView, IQrCodeDataView, IFaceLoginView { @@ -56,8 +70,6 @@ QMUIRoundButton loginButton; @BindView(R.id.rememberPasswordView) CheckBox rememberPasswordView; - @BindView(R.id.changeLoginModeView) - TextView changeLoginModeView; private QMUITipDialog loadingDialog; private AuthenticatePresenterImpl authenticatePresenter; @@ -130,7 +142,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } else { @@ -146,7 +158,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } @@ -156,6 +168,55 @@ } } + private void captureFaceData() { + //TODO 调相机,捕获人脸数据,并保存为文件得到路径 + PictureSelector.create(this) + .openCamera(PictureMimeType.ofImage()) + .imageEngine(GlideLoadEngine.createGlideEngine()) + .maxSelectNum(1) + .forResult(PictureConfig.REQUEST_CAMERA); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + if (requestCode == PictureConfig.REQUEST_CAMERA) { + LocalMedia localMedia = PictureSelector.obtainMultipleResult(data).get(0); + Luban.with(this) + .load(localMedia.getRealPath()) + .ignoreBy(100) + .setTargetDir(FileUtils.getFileDir("CompressImageFile")) + .filter(new CompressionPredicate() { + @Override + public boolean apply(String path) { + return !(TextUtils.isEmpty(path) || path.toLowerCase().endsWith(".gif")); + } + }) + .setCompressListener(new OnCompressListener() { + @Override + public void onStart() { + // TODO 压缩开始前调用,可以在方法内启动 loading UI + } + + @Override + public void onSuccess(File file) { + String imageToBase64 = StringHelper.imageToBase64(file); + + ImageBean imageBean = new ImageBean(); + imageBean.setImage(imageToBase64); + faceLoginPresenter.onReadyRetrofitRequest(imageBean); + } + + @Override + public void onError(Throwable e) { + // TODO 当压缩过程出现问题时调用 + } + }).launch(); + } + } + } + private void startScannerLogin() { QrConfig qrConfig = new QrConfig.Builder() .setTitleText("扫码登录")//设置Title文字 @@ -193,7 +254,7 @@ @Override public void authenticateResult(PublicKeyBean result) { -// Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); + Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); if (result.isSuccess()) { PublicKey publicKey = RSAUtils.keyStrToPublicKey(result.getData().getPublicKey()); if (TextUtils.isEmpty(userName)) { @@ -240,12 +301,22 @@ //验证成功登录 startActivity(new Intent(this, MainActivity.class)); finish(); + } else { + Toast.makeText(this, "二维码已失效", Toast.LENGTH_SHORT).show(); } } @Override public void obtainFaceLoginData(FaceLoginResultBean resultBean) { - +// Log.d(TAG, "obtainFaceLoginData: " + new Gson().toJson(resultBean)); + if (resultBean.getCode() == 200) { + TokenHelper.saveToken(resultBean.getData().getToken()); + //验证成功登录 + startActivity(new Intent(this, MainActivity.class)); + finish(); + } else { + Toast.makeText(this, "无法解析人脸", Toast.LENGTH_SHORT).show(); + } } @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java index 4baf176..f70848a 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java @@ -3,14 +3,14 @@ import androidx.core.content.ContextCompat; import com.casic.birmm.hxrq.R; -import com.casic.birmm.hxrq.base.BaseActivity; +import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.utils.SaveKeyValues; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.QMUITopBarLayout; import butterknife.BindView; -public class MainActivity extends BaseActivity { +public class MainActivity extends DoubleClickExitActivity { @BindView(R.id.mainTopLayout) QMUITopBarLayout mainTopLayout; diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java b/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java new file mode 100644 index 0000000..fc939a7 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java @@ -0,0 +1,34 @@ +package com.casic.birmm.hxrq.utils; + +import android.os.Environment; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +public class FileUtils { + + public static String getFileDir(String dirName) { + File imageDir = new File(Environment.getExternalStorageDirectory(), dirName); + if (!imageDir.exists()) { + imageDir.mkdir(); + } + return imageDir.toString(); + } + + public static File getFaceImageFile() { + String imageDir = getFileDir("FaceImageFile"); + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date()); + File imageFile = new File(imageDir + File.separator + "IMG_" + timeStamp + ".png"); + if (!imageFile.exists()) { + try { + imageFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return imageFile; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java b/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java new file mode 100644 index 0000000..6de07df --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java @@ -0,0 +1,89 @@ +package com.casic.birmm.hxrq.utils; + +import android.content.Context; +import android.graphics.Bitmap; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.core.graphics.drawable.RoundedBitmapDrawable; +import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; +import com.bumptech.glide.request.target.BitmapImageViewTarget; +import com.casic.birmm.hxrq.R; +import com.luck.picture.lib.engine.ImageEngine; +import com.luck.picture.lib.listener.OnImageCompleteCallback; +import com.luck.picture.lib.widget.longimage.SubsamplingScaleImageView; + +/** + * @Author: Pengxh + * @Time: 2021/4/7 15:54 + * @Emain: 290677893@qq.com + **/ +public class GlideLoadEngine implements ImageEngine { + + private GlideLoadEngine() { + + } + + private static GlideLoadEngine instance; + + public static GlideLoadEngine createGlideEngine() { + if (null == instance) { + synchronized (GlideLoadEngine.class) { + if (null == instance) { + instance = new GlideLoadEngine(); + } + } + } + return instance; + } + + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context).load(url).into(imageView); + } + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView, SubsamplingScaleImageView longImageView, OnImageCompleteCallback callback) { + + } + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView, SubsamplingScaleImageView longImageView) { + + } + + @Override + public void loadFolderImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context) + .asBitmap() + .load(url) + .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder)) + .into(new BitmapImageViewTarget(imageView) { + @Override + protected void setResource(Bitmap resource) { + RoundedBitmapDrawable circularBitmapDrawable = + RoundedBitmapDrawableFactory. + create(context.getResources(), resource); + circularBitmapDrawable.setCornerRadius(8); + imageView.setImageDrawable(circularBitmapDrawable); + } + }); + } + + @Override + public void loadAsGifImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context).asGif().load(url).into(imageView); + } + + @Override + public void loadGridImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context) + .load(url) + .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder)) + .into(imageView); + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java b/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java deleted file mode 100644 index 065eab3..0000000 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.casic.birmm.hxrq.utils; - -import android.util.Log; - -import com.casic.birmm.hxrq.utils.callback.ILoginResultListener; - -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; - -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import rx.Observable; -import rx.Subscriber; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; - -public class HttpHelper { - private static final String TAG = "HttpHelper"; - - public static void loginWithPassword(String url, String userName, String password, ILoginResultListener listener) { - Observable.create((Observable.OnSubscribe) subscriber -> - new OkHttpClient().newCall(new Request.Builder() - .url("http://111.198.10.15:20403/cockpit/mrg/login/") - .get() - .build()) - .enqueue(new Callback() { - @Override - public void onFailure(@NotNull Call call, @NotNull IOException e) { - subscriber.onError(e); - } - - @Override - public void onResponse(@NotNull Call call, @NotNull Response response) { - subscriber.onNext(response); - } - })).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber() { - @Override - public void onError(Throwable e) { - Log.d(TAG, "onError: " + e); - } - - @Override - public void onNext(Response response) { - if (response == null) { - Log.e(TAG, "请求出错: ", new NullPointerException()); - return; - } - try { - Log.d(TAG, "onNext: " + response.body().string()); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void onCompleted() { - Log.d(TAG, "onCompleted: 请求完成"); - } - }); - } -} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java b/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java index ec7bdb6..0ebf16a 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java @@ -1,5 +1,11 @@ package com.casic.birmm.hxrq.utils; +import android.util.Base64; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; + /** * @Author: Pengxh * @Time: 2021/4/9 15:12 @@ -8,6 +14,28 @@ public class StringHelper { /** * 获取图片base64编码 - * */ + */ + public static String imageToBase64(File file) { + if (file == null) { + return null; + } + try { + FileInputStream fis = new FileInputStream(file); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + byte[] b = new byte[1024]; + int n; + while ((n = fis.read(b)) != -1) { + bos.write(b, 0, n); + } + fis.close(); + bos.close(); + byte[] imgBytes = bos.toByteArray(); + String s = Base64.encodeToString(imgBytes, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING); + return s.replace("-", "+") + .replace("_", "/"); + } catch (Exception e) { + return null; + } + } } diff --git a/app/build.gradle b/app/build.gradle index f98f5bc..9d60011 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,4 +56,10 @@ implementation 'com.google.code.gson:gson:2.8.6' //ZBar扫一扫 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' + //图片选择框架 + implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.5.0' + //图片压缩框架 + implementation 'top.zibin:Luban:1.1.8' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2b7b378..c6065dc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/QMUI.Compat.NoActionBar" @@ -29,6 +30,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java new file mode 100644 index 0000000..e685c07 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java @@ -0,0 +1,18 @@ +package com.casic.birmm.hxrq.bean; + +/** + * @Author: Pengxh + * @Time: 2021/4/9 19:00 + * @Email: 290677893@qq.com + **/ +public class ImageBean { + private String image; + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java index 06c0332..d8b2ab7 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.model; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.utils.HttpConfig; import com.casic.birmm.hxrq.utils.retrofit.RetrofitServiceManager; @@ -33,7 +34,7 @@ } @Override - public Subscription sendRetrofitRequest(String image) { + public Subscription sendRetrofitRequest(ImageBean image) { Observable observable = RetrofitServiceManager.getFaceResult(HttpConfig.BASE_IP, image); return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer() { @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java index 5a14fee..c63312c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java @@ -1,8 +1,9 @@ package com.casic.birmm.hxrq.mvp.model; +import com.casic.birmm.hxrq.bean.ImageBean; + import rx.Subscription; public interface IFaceLoginModel { - //image传的是图片的base64编码 - Subscription sendRetrofitRequest(String image); + Subscription sendRetrofitRequest(ImageBean image); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java index 51e4f4f..7fb154c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.presenter; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.mvp.BasePresenter; import com.casic.birmm.hxrq.mvp.model.FaceLoginModelImpl; import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; @@ -21,7 +22,7 @@ } @Override - public void onReadyRetrofitRequest(String image) { + public void onReadyRetrofitRequest(ImageBean image) { addSubscription(actionModel.sendRetrofitRequest(image)); } @@ -30,6 +31,7 @@ unSubscription(); } + @Override public void onSuccess(FaceLoginResultBean resultBean) { view.obtainFaceLoginData(resultBean); diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java index f525a45..01a5512 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java @@ -1,12 +1,14 @@ package com.casic.birmm.hxrq.mvp.presenter; +import com.casic.birmm.hxrq.bean.ImageBean; + /** * @Author: Pengxh * @Time: 2021/4/9 14:55 * @Email: 290677893@qq.com **/ public interface IFaceLoginPresenter { - void onReadyRetrofitRequest(String image); + void onReadyRetrofitRequest(ImageBean image); void disposeRetrofitRequest(); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java index e9f01ce..98aef9d 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java @@ -9,12 +9,14 @@ import android.view.View; import android.widget.CheckBox; import android.widget.EditText; -import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.Nullable; + import com.casic.birmm.hxrq.R; import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.bean.LoginResultBean; import com.casic.birmm.hxrq.bean.PublicKeyBean; import com.casic.birmm.hxrq.bean.QrCodeBean; @@ -26,14 +28,23 @@ import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; import com.casic.birmm.hxrq.mvp.view.ILoginView; import com.casic.birmm.hxrq.mvp.view.IQrCodeDataView; +import com.casic.birmm.hxrq.utils.FileUtils; +import com.casic.birmm.hxrq.utils.GlideLoadEngine; import com.casic.birmm.hxrq.utils.RSAUtils; import com.casic.birmm.hxrq.utils.SaveKeyValues; +import com.casic.birmm.hxrq.utils.StringHelper; import com.casic.birmm.hxrq.utils.TokenHelper; +import com.google.gson.Gson; +import com.luck.picture.lib.PictureSelector; +import com.luck.picture.lib.config.PictureConfig; +import com.luck.picture.lib.config.PictureMimeType; +import com.luck.picture.lib.entity.LocalMedia; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.dialog.QMUIDialog; import com.qmuiteam.qmui.widget.dialog.QMUITipDialog; import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton; +import java.io.File; import java.security.PublicKey; import butterknife.BindView; @@ -42,6 +53,9 @@ import cn.bertsir.zbar.QrConfig; import cn.bertsir.zbar.QrManager; import cn.bertsir.zbar.view.ScanLineView; +import top.zibin.luban.CompressionPredicate; +import top.zibin.luban.Luban; +import top.zibin.luban.OnCompressListener; public class LoginActivity extends DoubleClickExitActivity implements View.OnClickListener, IAuthenticateView, ILoginView, IQrCodeDataView, IFaceLoginView { @@ -56,8 +70,6 @@ QMUIRoundButton loginButton; @BindView(R.id.rememberPasswordView) CheckBox rememberPasswordView; - @BindView(R.id.changeLoginModeView) - TextView changeLoginModeView; private QMUITipDialog loadingDialog; private AuthenticatePresenterImpl authenticatePresenter; @@ -130,7 +142,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } else { @@ -146,7 +158,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } @@ -156,6 +168,55 @@ } } + private void captureFaceData() { + //TODO 调相机,捕获人脸数据,并保存为文件得到路径 + PictureSelector.create(this) + .openCamera(PictureMimeType.ofImage()) + .imageEngine(GlideLoadEngine.createGlideEngine()) + .maxSelectNum(1) + .forResult(PictureConfig.REQUEST_CAMERA); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + if (requestCode == PictureConfig.REQUEST_CAMERA) { + LocalMedia localMedia = PictureSelector.obtainMultipleResult(data).get(0); + Luban.with(this) + .load(localMedia.getRealPath()) + .ignoreBy(100) + .setTargetDir(FileUtils.getFileDir("CompressImageFile")) + .filter(new CompressionPredicate() { + @Override + public boolean apply(String path) { + return !(TextUtils.isEmpty(path) || path.toLowerCase().endsWith(".gif")); + } + }) + .setCompressListener(new OnCompressListener() { + @Override + public void onStart() { + // TODO 压缩开始前调用,可以在方法内启动 loading UI + } + + @Override + public void onSuccess(File file) { + String imageToBase64 = StringHelper.imageToBase64(file); + + ImageBean imageBean = new ImageBean(); + imageBean.setImage(imageToBase64); + faceLoginPresenter.onReadyRetrofitRequest(imageBean); + } + + @Override + public void onError(Throwable e) { + // TODO 当压缩过程出现问题时调用 + } + }).launch(); + } + } + } + private void startScannerLogin() { QrConfig qrConfig = new QrConfig.Builder() .setTitleText("扫码登录")//设置Title文字 @@ -193,7 +254,7 @@ @Override public void authenticateResult(PublicKeyBean result) { -// Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); + Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); if (result.isSuccess()) { PublicKey publicKey = RSAUtils.keyStrToPublicKey(result.getData().getPublicKey()); if (TextUtils.isEmpty(userName)) { @@ -240,12 +301,22 @@ //验证成功登录 startActivity(new Intent(this, MainActivity.class)); finish(); + } else { + Toast.makeText(this, "二维码已失效", Toast.LENGTH_SHORT).show(); } } @Override public void obtainFaceLoginData(FaceLoginResultBean resultBean) { - +// Log.d(TAG, "obtainFaceLoginData: " + new Gson().toJson(resultBean)); + if (resultBean.getCode() == 200) { + TokenHelper.saveToken(resultBean.getData().getToken()); + //验证成功登录 + startActivity(new Intent(this, MainActivity.class)); + finish(); + } else { + Toast.makeText(this, "无法解析人脸", Toast.LENGTH_SHORT).show(); + } } @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java index 4baf176..f70848a 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java @@ -3,14 +3,14 @@ import androidx.core.content.ContextCompat; import com.casic.birmm.hxrq.R; -import com.casic.birmm.hxrq.base.BaseActivity; +import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.utils.SaveKeyValues; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.QMUITopBarLayout; import butterknife.BindView; -public class MainActivity extends BaseActivity { +public class MainActivity extends DoubleClickExitActivity { @BindView(R.id.mainTopLayout) QMUITopBarLayout mainTopLayout; diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java b/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java new file mode 100644 index 0000000..fc939a7 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java @@ -0,0 +1,34 @@ +package com.casic.birmm.hxrq.utils; + +import android.os.Environment; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +public class FileUtils { + + public static String getFileDir(String dirName) { + File imageDir = new File(Environment.getExternalStorageDirectory(), dirName); + if (!imageDir.exists()) { + imageDir.mkdir(); + } + return imageDir.toString(); + } + + public static File getFaceImageFile() { + String imageDir = getFileDir("FaceImageFile"); + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date()); + File imageFile = new File(imageDir + File.separator + "IMG_" + timeStamp + ".png"); + if (!imageFile.exists()) { + try { + imageFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return imageFile; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java b/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java new file mode 100644 index 0000000..6de07df --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java @@ -0,0 +1,89 @@ +package com.casic.birmm.hxrq.utils; + +import android.content.Context; +import android.graphics.Bitmap; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.core.graphics.drawable.RoundedBitmapDrawable; +import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; +import com.bumptech.glide.request.target.BitmapImageViewTarget; +import com.casic.birmm.hxrq.R; +import com.luck.picture.lib.engine.ImageEngine; +import com.luck.picture.lib.listener.OnImageCompleteCallback; +import com.luck.picture.lib.widget.longimage.SubsamplingScaleImageView; + +/** + * @Author: Pengxh + * @Time: 2021/4/7 15:54 + * @Emain: 290677893@qq.com + **/ +public class GlideLoadEngine implements ImageEngine { + + private GlideLoadEngine() { + + } + + private static GlideLoadEngine instance; + + public static GlideLoadEngine createGlideEngine() { + if (null == instance) { + synchronized (GlideLoadEngine.class) { + if (null == instance) { + instance = new GlideLoadEngine(); + } + } + } + return instance; + } + + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context).load(url).into(imageView); + } + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView, SubsamplingScaleImageView longImageView, OnImageCompleteCallback callback) { + + } + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView, SubsamplingScaleImageView longImageView) { + + } + + @Override + public void loadFolderImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context) + .asBitmap() + .load(url) + .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder)) + .into(new BitmapImageViewTarget(imageView) { + @Override + protected void setResource(Bitmap resource) { + RoundedBitmapDrawable circularBitmapDrawable = + RoundedBitmapDrawableFactory. + create(context.getResources(), resource); + circularBitmapDrawable.setCornerRadius(8); + imageView.setImageDrawable(circularBitmapDrawable); + } + }); + } + + @Override + public void loadAsGifImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context).asGif().load(url).into(imageView); + } + + @Override + public void loadGridImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context) + .load(url) + .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder)) + .into(imageView); + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java b/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java deleted file mode 100644 index 065eab3..0000000 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.casic.birmm.hxrq.utils; - -import android.util.Log; - -import com.casic.birmm.hxrq.utils.callback.ILoginResultListener; - -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; - -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import rx.Observable; -import rx.Subscriber; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; - -public class HttpHelper { - private static final String TAG = "HttpHelper"; - - public static void loginWithPassword(String url, String userName, String password, ILoginResultListener listener) { - Observable.create((Observable.OnSubscribe) subscriber -> - new OkHttpClient().newCall(new Request.Builder() - .url("http://111.198.10.15:20403/cockpit/mrg/login/") - .get() - .build()) - .enqueue(new Callback() { - @Override - public void onFailure(@NotNull Call call, @NotNull IOException e) { - subscriber.onError(e); - } - - @Override - public void onResponse(@NotNull Call call, @NotNull Response response) { - subscriber.onNext(response); - } - })).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber() { - @Override - public void onError(Throwable e) { - Log.d(TAG, "onError: " + e); - } - - @Override - public void onNext(Response response) { - if (response == null) { - Log.e(TAG, "请求出错: ", new NullPointerException()); - return; - } - try { - Log.d(TAG, "onNext: " + response.body().string()); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void onCompleted() { - Log.d(TAG, "onCompleted: 请求完成"); - } - }); - } -} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java b/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java index ec7bdb6..0ebf16a 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java @@ -1,5 +1,11 @@ package com.casic.birmm.hxrq.utils; +import android.util.Base64; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; + /** * @Author: Pengxh * @Time: 2021/4/9 15:12 @@ -8,6 +14,28 @@ public class StringHelper { /** * 获取图片base64编码 - * */ + */ + public static String imageToBase64(File file) { + if (file == null) { + return null; + } + try { + FileInputStream fis = new FileInputStream(file); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + byte[] b = new byte[1024]; + int n; + while ((n = fis.read(b)) != -1) { + bos.write(b, 0, n); + } + fis.close(); + bos.close(); + byte[] imgBytes = bos.toByteArray(); + String s = Base64.encodeToString(imgBytes, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING); + return s.replace("-", "+") + .replace("_", "/"); + } catch (Exception e) { + return null; + } + } } diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/callback/ILoginResultListener.java b/app/src/main/java/com/casic/birmm/hxrq/utils/callback/ILoginResultListener.java deleted file mode 100644 index b292c97..0000000 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/callback/ILoginResultListener.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.casic.birmm.hxrq.utils.callback; - -public interface ILoginResultListener { - void onLoginIn(); -} diff --git a/app/build.gradle b/app/build.gradle index f98f5bc..9d60011 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,4 +56,10 @@ implementation 'com.google.code.gson:gson:2.8.6' //ZBar扫一扫 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' + //图片选择框架 + implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.5.0' + //图片压缩框架 + implementation 'top.zibin:Luban:1.1.8' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2b7b378..c6065dc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/QMUI.Compat.NoActionBar" @@ -29,6 +30,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java new file mode 100644 index 0000000..e685c07 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java @@ -0,0 +1,18 @@ +package com.casic.birmm.hxrq.bean; + +/** + * @Author: Pengxh + * @Time: 2021/4/9 19:00 + * @Email: 290677893@qq.com + **/ +public class ImageBean { + private String image; + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java index 06c0332..d8b2ab7 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.model; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.utils.HttpConfig; import com.casic.birmm.hxrq.utils.retrofit.RetrofitServiceManager; @@ -33,7 +34,7 @@ } @Override - public Subscription sendRetrofitRequest(String image) { + public Subscription sendRetrofitRequest(ImageBean image) { Observable observable = RetrofitServiceManager.getFaceResult(HttpConfig.BASE_IP, image); return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer() { @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java index 5a14fee..c63312c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java @@ -1,8 +1,9 @@ package com.casic.birmm.hxrq.mvp.model; +import com.casic.birmm.hxrq.bean.ImageBean; + import rx.Subscription; public interface IFaceLoginModel { - //image传的是图片的base64编码 - Subscription sendRetrofitRequest(String image); + Subscription sendRetrofitRequest(ImageBean image); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java index 51e4f4f..7fb154c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.presenter; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.mvp.BasePresenter; import com.casic.birmm.hxrq.mvp.model.FaceLoginModelImpl; import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; @@ -21,7 +22,7 @@ } @Override - public void onReadyRetrofitRequest(String image) { + public void onReadyRetrofitRequest(ImageBean image) { addSubscription(actionModel.sendRetrofitRequest(image)); } @@ -30,6 +31,7 @@ unSubscription(); } + @Override public void onSuccess(FaceLoginResultBean resultBean) { view.obtainFaceLoginData(resultBean); diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java index f525a45..01a5512 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java @@ -1,12 +1,14 @@ package com.casic.birmm.hxrq.mvp.presenter; +import com.casic.birmm.hxrq.bean.ImageBean; + /** * @Author: Pengxh * @Time: 2021/4/9 14:55 * @Email: 290677893@qq.com **/ public interface IFaceLoginPresenter { - void onReadyRetrofitRequest(String image); + void onReadyRetrofitRequest(ImageBean image); void disposeRetrofitRequest(); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java index e9f01ce..98aef9d 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java @@ -9,12 +9,14 @@ import android.view.View; import android.widget.CheckBox; import android.widget.EditText; -import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.Nullable; + import com.casic.birmm.hxrq.R; import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.bean.LoginResultBean; import com.casic.birmm.hxrq.bean.PublicKeyBean; import com.casic.birmm.hxrq.bean.QrCodeBean; @@ -26,14 +28,23 @@ import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; import com.casic.birmm.hxrq.mvp.view.ILoginView; import com.casic.birmm.hxrq.mvp.view.IQrCodeDataView; +import com.casic.birmm.hxrq.utils.FileUtils; +import com.casic.birmm.hxrq.utils.GlideLoadEngine; import com.casic.birmm.hxrq.utils.RSAUtils; import com.casic.birmm.hxrq.utils.SaveKeyValues; +import com.casic.birmm.hxrq.utils.StringHelper; import com.casic.birmm.hxrq.utils.TokenHelper; +import com.google.gson.Gson; +import com.luck.picture.lib.PictureSelector; +import com.luck.picture.lib.config.PictureConfig; +import com.luck.picture.lib.config.PictureMimeType; +import com.luck.picture.lib.entity.LocalMedia; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.dialog.QMUIDialog; import com.qmuiteam.qmui.widget.dialog.QMUITipDialog; import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton; +import java.io.File; import java.security.PublicKey; import butterknife.BindView; @@ -42,6 +53,9 @@ import cn.bertsir.zbar.QrConfig; import cn.bertsir.zbar.QrManager; import cn.bertsir.zbar.view.ScanLineView; +import top.zibin.luban.CompressionPredicate; +import top.zibin.luban.Luban; +import top.zibin.luban.OnCompressListener; public class LoginActivity extends DoubleClickExitActivity implements View.OnClickListener, IAuthenticateView, ILoginView, IQrCodeDataView, IFaceLoginView { @@ -56,8 +70,6 @@ QMUIRoundButton loginButton; @BindView(R.id.rememberPasswordView) CheckBox rememberPasswordView; - @BindView(R.id.changeLoginModeView) - TextView changeLoginModeView; private QMUITipDialog loadingDialog; private AuthenticatePresenterImpl authenticatePresenter; @@ -130,7 +142,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } else { @@ -146,7 +158,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } @@ -156,6 +168,55 @@ } } + private void captureFaceData() { + //TODO 调相机,捕获人脸数据,并保存为文件得到路径 + PictureSelector.create(this) + .openCamera(PictureMimeType.ofImage()) + .imageEngine(GlideLoadEngine.createGlideEngine()) + .maxSelectNum(1) + .forResult(PictureConfig.REQUEST_CAMERA); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + if (requestCode == PictureConfig.REQUEST_CAMERA) { + LocalMedia localMedia = PictureSelector.obtainMultipleResult(data).get(0); + Luban.with(this) + .load(localMedia.getRealPath()) + .ignoreBy(100) + .setTargetDir(FileUtils.getFileDir("CompressImageFile")) + .filter(new CompressionPredicate() { + @Override + public boolean apply(String path) { + return !(TextUtils.isEmpty(path) || path.toLowerCase().endsWith(".gif")); + } + }) + .setCompressListener(new OnCompressListener() { + @Override + public void onStart() { + // TODO 压缩开始前调用,可以在方法内启动 loading UI + } + + @Override + public void onSuccess(File file) { + String imageToBase64 = StringHelper.imageToBase64(file); + + ImageBean imageBean = new ImageBean(); + imageBean.setImage(imageToBase64); + faceLoginPresenter.onReadyRetrofitRequest(imageBean); + } + + @Override + public void onError(Throwable e) { + // TODO 当压缩过程出现问题时调用 + } + }).launch(); + } + } + } + private void startScannerLogin() { QrConfig qrConfig = new QrConfig.Builder() .setTitleText("扫码登录")//设置Title文字 @@ -193,7 +254,7 @@ @Override public void authenticateResult(PublicKeyBean result) { -// Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); + Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); if (result.isSuccess()) { PublicKey publicKey = RSAUtils.keyStrToPublicKey(result.getData().getPublicKey()); if (TextUtils.isEmpty(userName)) { @@ -240,12 +301,22 @@ //验证成功登录 startActivity(new Intent(this, MainActivity.class)); finish(); + } else { + Toast.makeText(this, "二维码已失效", Toast.LENGTH_SHORT).show(); } } @Override public void obtainFaceLoginData(FaceLoginResultBean resultBean) { - +// Log.d(TAG, "obtainFaceLoginData: " + new Gson().toJson(resultBean)); + if (resultBean.getCode() == 200) { + TokenHelper.saveToken(resultBean.getData().getToken()); + //验证成功登录 + startActivity(new Intent(this, MainActivity.class)); + finish(); + } else { + Toast.makeText(this, "无法解析人脸", Toast.LENGTH_SHORT).show(); + } } @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java index 4baf176..f70848a 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java @@ -3,14 +3,14 @@ import androidx.core.content.ContextCompat; import com.casic.birmm.hxrq.R; -import com.casic.birmm.hxrq.base.BaseActivity; +import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.utils.SaveKeyValues; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.QMUITopBarLayout; import butterknife.BindView; -public class MainActivity extends BaseActivity { +public class MainActivity extends DoubleClickExitActivity { @BindView(R.id.mainTopLayout) QMUITopBarLayout mainTopLayout; diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java b/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java new file mode 100644 index 0000000..fc939a7 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java @@ -0,0 +1,34 @@ +package com.casic.birmm.hxrq.utils; + +import android.os.Environment; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +public class FileUtils { + + public static String getFileDir(String dirName) { + File imageDir = new File(Environment.getExternalStorageDirectory(), dirName); + if (!imageDir.exists()) { + imageDir.mkdir(); + } + return imageDir.toString(); + } + + public static File getFaceImageFile() { + String imageDir = getFileDir("FaceImageFile"); + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date()); + File imageFile = new File(imageDir + File.separator + "IMG_" + timeStamp + ".png"); + if (!imageFile.exists()) { + try { + imageFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return imageFile; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java b/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java new file mode 100644 index 0000000..6de07df --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java @@ -0,0 +1,89 @@ +package com.casic.birmm.hxrq.utils; + +import android.content.Context; +import android.graphics.Bitmap; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.core.graphics.drawable.RoundedBitmapDrawable; +import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; +import com.bumptech.glide.request.target.BitmapImageViewTarget; +import com.casic.birmm.hxrq.R; +import com.luck.picture.lib.engine.ImageEngine; +import com.luck.picture.lib.listener.OnImageCompleteCallback; +import com.luck.picture.lib.widget.longimage.SubsamplingScaleImageView; + +/** + * @Author: Pengxh + * @Time: 2021/4/7 15:54 + * @Emain: 290677893@qq.com + **/ +public class GlideLoadEngine implements ImageEngine { + + private GlideLoadEngine() { + + } + + private static GlideLoadEngine instance; + + public static GlideLoadEngine createGlideEngine() { + if (null == instance) { + synchronized (GlideLoadEngine.class) { + if (null == instance) { + instance = new GlideLoadEngine(); + } + } + } + return instance; + } + + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context).load(url).into(imageView); + } + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView, SubsamplingScaleImageView longImageView, OnImageCompleteCallback callback) { + + } + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView, SubsamplingScaleImageView longImageView) { + + } + + @Override + public void loadFolderImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context) + .asBitmap() + .load(url) + .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder)) + .into(new BitmapImageViewTarget(imageView) { + @Override + protected void setResource(Bitmap resource) { + RoundedBitmapDrawable circularBitmapDrawable = + RoundedBitmapDrawableFactory. + create(context.getResources(), resource); + circularBitmapDrawable.setCornerRadius(8); + imageView.setImageDrawable(circularBitmapDrawable); + } + }); + } + + @Override + public void loadAsGifImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context).asGif().load(url).into(imageView); + } + + @Override + public void loadGridImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context) + .load(url) + .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder)) + .into(imageView); + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java b/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java deleted file mode 100644 index 065eab3..0000000 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.casic.birmm.hxrq.utils; - -import android.util.Log; - -import com.casic.birmm.hxrq.utils.callback.ILoginResultListener; - -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; - -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import rx.Observable; -import rx.Subscriber; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; - -public class HttpHelper { - private static final String TAG = "HttpHelper"; - - public static void loginWithPassword(String url, String userName, String password, ILoginResultListener listener) { - Observable.create((Observable.OnSubscribe) subscriber -> - new OkHttpClient().newCall(new Request.Builder() - .url("http://111.198.10.15:20403/cockpit/mrg/login/") - .get() - .build()) - .enqueue(new Callback() { - @Override - public void onFailure(@NotNull Call call, @NotNull IOException e) { - subscriber.onError(e); - } - - @Override - public void onResponse(@NotNull Call call, @NotNull Response response) { - subscriber.onNext(response); - } - })).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber() { - @Override - public void onError(Throwable e) { - Log.d(TAG, "onError: " + e); - } - - @Override - public void onNext(Response response) { - if (response == null) { - Log.e(TAG, "请求出错: ", new NullPointerException()); - return; - } - try { - Log.d(TAG, "onNext: " + response.body().string()); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void onCompleted() { - Log.d(TAG, "onCompleted: 请求完成"); - } - }); - } -} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java b/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java index ec7bdb6..0ebf16a 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java @@ -1,5 +1,11 @@ package com.casic.birmm.hxrq.utils; +import android.util.Base64; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; + /** * @Author: Pengxh * @Time: 2021/4/9 15:12 @@ -8,6 +14,28 @@ public class StringHelper { /** * 获取图片base64编码 - * */ + */ + public static String imageToBase64(File file) { + if (file == null) { + return null; + } + try { + FileInputStream fis = new FileInputStream(file); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + byte[] b = new byte[1024]; + int n; + while ((n = fis.read(b)) != -1) { + bos.write(b, 0, n); + } + fis.close(); + bos.close(); + byte[] imgBytes = bos.toByteArray(); + String s = Base64.encodeToString(imgBytes, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING); + return s.replace("-", "+") + .replace("_", "/"); + } catch (Exception e) { + return null; + } + } } diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/callback/ILoginResultListener.java b/app/src/main/java/com/casic/birmm/hxrq/utils/callback/ILoginResultListener.java deleted file mode 100644 index b292c97..0000000 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/callback/ILoginResultListener.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.casic.birmm.hxrq.utils.callback; - -public interface ILoginResultListener { - void onLoginIn(); -} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitService.java b/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitService.java index 067e020..8fe5264 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitService.java +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitService.java @@ -1,14 +1,17 @@ package com.casic.birmm.hxrq.utils.retrofit; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.bean.LoginResultBean; import com.casic.birmm.hxrq.bean.PublicKeyBean; import com.casic.birmm.hxrq.bean.QrCodeBean; +import retrofit2.http.Body; import retrofit2.http.Field; import retrofit2.http.FormUrlEncoded; import retrofit2.http.GET; import retrofit2.http.Header; +import retrofit2.http.Headers; import retrofit2.http.POST; import retrofit2.http.Query; import rx.Observable; @@ -41,8 +44,11 @@ @Header("token") String token, @Query("qrcodeId") String qrcodeId); - @FormUrlEncoded + /** + * 人脸登录 + */ + @Headers({"Content-Type: application/json"}) @POST("/cockpit/face/login") Observable getFaceLoginResult( - @Field("image") String image); + @Body ImageBean imageBean); } diff --git a/app/build.gradle b/app/build.gradle index f98f5bc..9d60011 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,4 +56,10 @@ implementation 'com.google.code.gson:gson:2.8.6' //ZBar扫一扫 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' + //图片选择框架 + implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.5.0' + //图片压缩框架 + implementation 'top.zibin:Luban:1.1.8' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2b7b378..c6065dc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/QMUI.Compat.NoActionBar" @@ -29,6 +30,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java new file mode 100644 index 0000000..e685c07 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java @@ -0,0 +1,18 @@ +package com.casic.birmm.hxrq.bean; + +/** + * @Author: Pengxh + * @Time: 2021/4/9 19:00 + * @Email: 290677893@qq.com + **/ +public class ImageBean { + private String image; + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java index 06c0332..d8b2ab7 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.model; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.utils.HttpConfig; import com.casic.birmm.hxrq.utils.retrofit.RetrofitServiceManager; @@ -33,7 +34,7 @@ } @Override - public Subscription sendRetrofitRequest(String image) { + public Subscription sendRetrofitRequest(ImageBean image) { Observable observable = RetrofitServiceManager.getFaceResult(HttpConfig.BASE_IP, image); return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer() { @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java index 5a14fee..c63312c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java @@ -1,8 +1,9 @@ package com.casic.birmm.hxrq.mvp.model; +import com.casic.birmm.hxrq.bean.ImageBean; + import rx.Subscription; public interface IFaceLoginModel { - //image传的是图片的base64编码 - Subscription sendRetrofitRequest(String image); + Subscription sendRetrofitRequest(ImageBean image); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java index 51e4f4f..7fb154c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.presenter; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.mvp.BasePresenter; import com.casic.birmm.hxrq.mvp.model.FaceLoginModelImpl; import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; @@ -21,7 +22,7 @@ } @Override - public void onReadyRetrofitRequest(String image) { + public void onReadyRetrofitRequest(ImageBean image) { addSubscription(actionModel.sendRetrofitRequest(image)); } @@ -30,6 +31,7 @@ unSubscription(); } + @Override public void onSuccess(FaceLoginResultBean resultBean) { view.obtainFaceLoginData(resultBean); diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java index f525a45..01a5512 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java @@ -1,12 +1,14 @@ package com.casic.birmm.hxrq.mvp.presenter; +import com.casic.birmm.hxrq.bean.ImageBean; + /** * @Author: Pengxh * @Time: 2021/4/9 14:55 * @Email: 290677893@qq.com **/ public interface IFaceLoginPresenter { - void onReadyRetrofitRequest(String image); + void onReadyRetrofitRequest(ImageBean image); void disposeRetrofitRequest(); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java index e9f01ce..98aef9d 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java @@ -9,12 +9,14 @@ import android.view.View; import android.widget.CheckBox; import android.widget.EditText; -import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.Nullable; + import com.casic.birmm.hxrq.R; import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.bean.LoginResultBean; import com.casic.birmm.hxrq.bean.PublicKeyBean; import com.casic.birmm.hxrq.bean.QrCodeBean; @@ -26,14 +28,23 @@ import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; import com.casic.birmm.hxrq.mvp.view.ILoginView; import com.casic.birmm.hxrq.mvp.view.IQrCodeDataView; +import com.casic.birmm.hxrq.utils.FileUtils; +import com.casic.birmm.hxrq.utils.GlideLoadEngine; import com.casic.birmm.hxrq.utils.RSAUtils; import com.casic.birmm.hxrq.utils.SaveKeyValues; +import com.casic.birmm.hxrq.utils.StringHelper; import com.casic.birmm.hxrq.utils.TokenHelper; +import com.google.gson.Gson; +import com.luck.picture.lib.PictureSelector; +import com.luck.picture.lib.config.PictureConfig; +import com.luck.picture.lib.config.PictureMimeType; +import com.luck.picture.lib.entity.LocalMedia; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.dialog.QMUIDialog; import com.qmuiteam.qmui.widget.dialog.QMUITipDialog; import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton; +import java.io.File; import java.security.PublicKey; import butterknife.BindView; @@ -42,6 +53,9 @@ import cn.bertsir.zbar.QrConfig; import cn.bertsir.zbar.QrManager; import cn.bertsir.zbar.view.ScanLineView; +import top.zibin.luban.CompressionPredicate; +import top.zibin.luban.Luban; +import top.zibin.luban.OnCompressListener; public class LoginActivity extends DoubleClickExitActivity implements View.OnClickListener, IAuthenticateView, ILoginView, IQrCodeDataView, IFaceLoginView { @@ -56,8 +70,6 @@ QMUIRoundButton loginButton; @BindView(R.id.rememberPasswordView) CheckBox rememberPasswordView; - @BindView(R.id.changeLoginModeView) - TextView changeLoginModeView; private QMUITipDialog loadingDialog; private AuthenticatePresenterImpl authenticatePresenter; @@ -130,7 +142,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } else { @@ -146,7 +158,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } @@ -156,6 +168,55 @@ } } + private void captureFaceData() { + //TODO 调相机,捕获人脸数据,并保存为文件得到路径 + PictureSelector.create(this) + .openCamera(PictureMimeType.ofImage()) + .imageEngine(GlideLoadEngine.createGlideEngine()) + .maxSelectNum(1) + .forResult(PictureConfig.REQUEST_CAMERA); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + if (requestCode == PictureConfig.REQUEST_CAMERA) { + LocalMedia localMedia = PictureSelector.obtainMultipleResult(data).get(0); + Luban.with(this) + .load(localMedia.getRealPath()) + .ignoreBy(100) + .setTargetDir(FileUtils.getFileDir("CompressImageFile")) + .filter(new CompressionPredicate() { + @Override + public boolean apply(String path) { + return !(TextUtils.isEmpty(path) || path.toLowerCase().endsWith(".gif")); + } + }) + .setCompressListener(new OnCompressListener() { + @Override + public void onStart() { + // TODO 压缩开始前调用,可以在方法内启动 loading UI + } + + @Override + public void onSuccess(File file) { + String imageToBase64 = StringHelper.imageToBase64(file); + + ImageBean imageBean = new ImageBean(); + imageBean.setImage(imageToBase64); + faceLoginPresenter.onReadyRetrofitRequest(imageBean); + } + + @Override + public void onError(Throwable e) { + // TODO 当压缩过程出现问题时调用 + } + }).launch(); + } + } + } + private void startScannerLogin() { QrConfig qrConfig = new QrConfig.Builder() .setTitleText("扫码登录")//设置Title文字 @@ -193,7 +254,7 @@ @Override public void authenticateResult(PublicKeyBean result) { -// Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); + Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); if (result.isSuccess()) { PublicKey publicKey = RSAUtils.keyStrToPublicKey(result.getData().getPublicKey()); if (TextUtils.isEmpty(userName)) { @@ -240,12 +301,22 @@ //验证成功登录 startActivity(new Intent(this, MainActivity.class)); finish(); + } else { + Toast.makeText(this, "二维码已失效", Toast.LENGTH_SHORT).show(); } } @Override public void obtainFaceLoginData(FaceLoginResultBean resultBean) { - +// Log.d(TAG, "obtainFaceLoginData: " + new Gson().toJson(resultBean)); + if (resultBean.getCode() == 200) { + TokenHelper.saveToken(resultBean.getData().getToken()); + //验证成功登录 + startActivity(new Intent(this, MainActivity.class)); + finish(); + } else { + Toast.makeText(this, "无法解析人脸", Toast.LENGTH_SHORT).show(); + } } @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java index 4baf176..f70848a 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java @@ -3,14 +3,14 @@ import androidx.core.content.ContextCompat; import com.casic.birmm.hxrq.R; -import com.casic.birmm.hxrq.base.BaseActivity; +import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.utils.SaveKeyValues; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.QMUITopBarLayout; import butterknife.BindView; -public class MainActivity extends BaseActivity { +public class MainActivity extends DoubleClickExitActivity { @BindView(R.id.mainTopLayout) QMUITopBarLayout mainTopLayout; diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java b/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java new file mode 100644 index 0000000..fc939a7 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java @@ -0,0 +1,34 @@ +package com.casic.birmm.hxrq.utils; + +import android.os.Environment; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +public class FileUtils { + + public static String getFileDir(String dirName) { + File imageDir = new File(Environment.getExternalStorageDirectory(), dirName); + if (!imageDir.exists()) { + imageDir.mkdir(); + } + return imageDir.toString(); + } + + public static File getFaceImageFile() { + String imageDir = getFileDir("FaceImageFile"); + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date()); + File imageFile = new File(imageDir + File.separator + "IMG_" + timeStamp + ".png"); + if (!imageFile.exists()) { + try { + imageFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return imageFile; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java b/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java new file mode 100644 index 0000000..6de07df --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java @@ -0,0 +1,89 @@ +package com.casic.birmm.hxrq.utils; + +import android.content.Context; +import android.graphics.Bitmap; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.core.graphics.drawable.RoundedBitmapDrawable; +import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; +import com.bumptech.glide.request.target.BitmapImageViewTarget; +import com.casic.birmm.hxrq.R; +import com.luck.picture.lib.engine.ImageEngine; +import com.luck.picture.lib.listener.OnImageCompleteCallback; +import com.luck.picture.lib.widget.longimage.SubsamplingScaleImageView; + +/** + * @Author: Pengxh + * @Time: 2021/4/7 15:54 + * @Emain: 290677893@qq.com + **/ +public class GlideLoadEngine implements ImageEngine { + + private GlideLoadEngine() { + + } + + private static GlideLoadEngine instance; + + public static GlideLoadEngine createGlideEngine() { + if (null == instance) { + synchronized (GlideLoadEngine.class) { + if (null == instance) { + instance = new GlideLoadEngine(); + } + } + } + return instance; + } + + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context).load(url).into(imageView); + } + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView, SubsamplingScaleImageView longImageView, OnImageCompleteCallback callback) { + + } + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView, SubsamplingScaleImageView longImageView) { + + } + + @Override + public void loadFolderImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context) + .asBitmap() + .load(url) + .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder)) + .into(new BitmapImageViewTarget(imageView) { + @Override + protected void setResource(Bitmap resource) { + RoundedBitmapDrawable circularBitmapDrawable = + RoundedBitmapDrawableFactory. + create(context.getResources(), resource); + circularBitmapDrawable.setCornerRadius(8); + imageView.setImageDrawable(circularBitmapDrawable); + } + }); + } + + @Override + public void loadAsGifImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context).asGif().load(url).into(imageView); + } + + @Override + public void loadGridImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context) + .load(url) + .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder)) + .into(imageView); + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java b/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java deleted file mode 100644 index 065eab3..0000000 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.casic.birmm.hxrq.utils; - -import android.util.Log; - -import com.casic.birmm.hxrq.utils.callback.ILoginResultListener; - -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; - -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import rx.Observable; -import rx.Subscriber; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; - -public class HttpHelper { - private static final String TAG = "HttpHelper"; - - public static void loginWithPassword(String url, String userName, String password, ILoginResultListener listener) { - Observable.create((Observable.OnSubscribe) subscriber -> - new OkHttpClient().newCall(new Request.Builder() - .url("http://111.198.10.15:20403/cockpit/mrg/login/") - .get() - .build()) - .enqueue(new Callback() { - @Override - public void onFailure(@NotNull Call call, @NotNull IOException e) { - subscriber.onError(e); - } - - @Override - public void onResponse(@NotNull Call call, @NotNull Response response) { - subscriber.onNext(response); - } - })).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber() { - @Override - public void onError(Throwable e) { - Log.d(TAG, "onError: " + e); - } - - @Override - public void onNext(Response response) { - if (response == null) { - Log.e(TAG, "请求出错: ", new NullPointerException()); - return; - } - try { - Log.d(TAG, "onNext: " + response.body().string()); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void onCompleted() { - Log.d(TAG, "onCompleted: 请求完成"); - } - }); - } -} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java b/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java index ec7bdb6..0ebf16a 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java @@ -1,5 +1,11 @@ package com.casic.birmm.hxrq.utils; +import android.util.Base64; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; + /** * @Author: Pengxh * @Time: 2021/4/9 15:12 @@ -8,6 +14,28 @@ public class StringHelper { /** * 获取图片base64编码 - * */ + */ + public static String imageToBase64(File file) { + if (file == null) { + return null; + } + try { + FileInputStream fis = new FileInputStream(file); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + byte[] b = new byte[1024]; + int n; + while ((n = fis.read(b)) != -1) { + bos.write(b, 0, n); + } + fis.close(); + bos.close(); + byte[] imgBytes = bos.toByteArray(); + String s = Base64.encodeToString(imgBytes, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING); + return s.replace("-", "+") + .replace("_", "/"); + } catch (Exception e) { + return null; + } + } } diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/callback/ILoginResultListener.java b/app/src/main/java/com/casic/birmm/hxrq/utils/callback/ILoginResultListener.java deleted file mode 100644 index b292c97..0000000 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/callback/ILoginResultListener.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.casic.birmm.hxrq.utils.callback; - -public interface ILoginResultListener { - void onLoginIn(); -} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitService.java b/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitService.java index 067e020..8fe5264 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitService.java +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitService.java @@ -1,14 +1,17 @@ package com.casic.birmm.hxrq.utils.retrofit; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.bean.LoginResultBean; import com.casic.birmm.hxrq.bean.PublicKeyBean; import com.casic.birmm.hxrq.bean.QrCodeBean; +import retrofit2.http.Body; import retrofit2.http.Field; import retrofit2.http.FormUrlEncoded; import retrofit2.http.GET; import retrofit2.http.Header; +import retrofit2.http.Headers; import retrofit2.http.POST; import retrofit2.http.Query; import rx.Observable; @@ -41,8 +44,11 @@ @Header("token") String token, @Query("qrcodeId") String qrcodeId); - @FormUrlEncoded + /** + * 人脸登录 + */ + @Headers({"Content-Type: application/json"}) @POST("/cockpit/face/login") Observable getFaceLoginResult( - @Field("image") String image); + @Body ImageBean imageBean); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitServiceManager.java b/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitServiceManager.java index 590bd91..ef4307e 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitServiceManager.java +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitServiceManager.java @@ -3,12 +3,14 @@ import android.util.Log; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.bean.LoginResultBean; import com.casic.birmm.hxrq.bean.PublicKeyBean; import com.casic.birmm.hxrq.bean.QrCodeBean; import com.casic.birmm.hxrq.utils.HttpConfig; import org.jetbrains.annotations.NotNull; +import org.json.JSONObject; import java.util.concurrent.TimeUnit; @@ -77,9 +79,9 @@ /** * 人脸识别登录结果 */ - public static Observable getFaceResult(String baseUrl, String image) { + public static Observable getFaceResult(String baseUrl, ImageBean imageBean) { Retrofit retrofit = createRetrofit(baseUrl); RetrofitService service = retrofit.create(RetrofitService.class); - return service.getFaceLoginResult(image); + return service.getFaceLoginResult(imageBean); } } diff --git a/app/build.gradle b/app/build.gradle index f98f5bc..9d60011 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,4 +56,10 @@ implementation 'com.google.code.gson:gson:2.8.6' //ZBar扫一扫 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' + //图片选择框架 + implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.5.0' + //图片压缩框架 + implementation 'top.zibin:Luban:1.1.8' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2b7b378..c6065dc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/QMUI.Compat.NoActionBar" @@ -29,6 +30,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java new file mode 100644 index 0000000..e685c07 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java @@ -0,0 +1,18 @@ +package com.casic.birmm.hxrq.bean; + +/** + * @Author: Pengxh + * @Time: 2021/4/9 19:00 + * @Email: 290677893@qq.com + **/ +public class ImageBean { + private String image; + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java index 06c0332..d8b2ab7 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.model; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.utils.HttpConfig; import com.casic.birmm.hxrq.utils.retrofit.RetrofitServiceManager; @@ -33,7 +34,7 @@ } @Override - public Subscription sendRetrofitRequest(String image) { + public Subscription sendRetrofitRequest(ImageBean image) { Observable observable = RetrofitServiceManager.getFaceResult(HttpConfig.BASE_IP, image); return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer() { @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java index 5a14fee..c63312c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java @@ -1,8 +1,9 @@ package com.casic.birmm.hxrq.mvp.model; +import com.casic.birmm.hxrq.bean.ImageBean; + import rx.Subscription; public interface IFaceLoginModel { - //image传的是图片的base64编码 - Subscription sendRetrofitRequest(String image); + Subscription sendRetrofitRequest(ImageBean image); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java index 51e4f4f..7fb154c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.presenter; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.mvp.BasePresenter; import com.casic.birmm.hxrq.mvp.model.FaceLoginModelImpl; import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; @@ -21,7 +22,7 @@ } @Override - public void onReadyRetrofitRequest(String image) { + public void onReadyRetrofitRequest(ImageBean image) { addSubscription(actionModel.sendRetrofitRequest(image)); } @@ -30,6 +31,7 @@ unSubscription(); } + @Override public void onSuccess(FaceLoginResultBean resultBean) { view.obtainFaceLoginData(resultBean); diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java index f525a45..01a5512 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java @@ -1,12 +1,14 @@ package com.casic.birmm.hxrq.mvp.presenter; +import com.casic.birmm.hxrq.bean.ImageBean; + /** * @Author: Pengxh * @Time: 2021/4/9 14:55 * @Email: 290677893@qq.com **/ public interface IFaceLoginPresenter { - void onReadyRetrofitRequest(String image); + void onReadyRetrofitRequest(ImageBean image); void disposeRetrofitRequest(); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java index e9f01ce..98aef9d 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java @@ -9,12 +9,14 @@ import android.view.View; import android.widget.CheckBox; import android.widget.EditText; -import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.Nullable; + import com.casic.birmm.hxrq.R; import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.bean.LoginResultBean; import com.casic.birmm.hxrq.bean.PublicKeyBean; import com.casic.birmm.hxrq.bean.QrCodeBean; @@ -26,14 +28,23 @@ import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; import com.casic.birmm.hxrq.mvp.view.ILoginView; import com.casic.birmm.hxrq.mvp.view.IQrCodeDataView; +import com.casic.birmm.hxrq.utils.FileUtils; +import com.casic.birmm.hxrq.utils.GlideLoadEngine; import com.casic.birmm.hxrq.utils.RSAUtils; import com.casic.birmm.hxrq.utils.SaveKeyValues; +import com.casic.birmm.hxrq.utils.StringHelper; import com.casic.birmm.hxrq.utils.TokenHelper; +import com.google.gson.Gson; +import com.luck.picture.lib.PictureSelector; +import com.luck.picture.lib.config.PictureConfig; +import com.luck.picture.lib.config.PictureMimeType; +import com.luck.picture.lib.entity.LocalMedia; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.dialog.QMUIDialog; import com.qmuiteam.qmui.widget.dialog.QMUITipDialog; import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton; +import java.io.File; import java.security.PublicKey; import butterknife.BindView; @@ -42,6 +53,9 @@ import cn.bertsir.zbar.QrConfig; import cn.bertsir.zbar.QrManager; import cn.bertsir.zbar.view.ScanLineView; +import top.zibin.luban.CompressionPredicate; +import top.zibin.luban.Luban; +import top.zibin.luban.OnCompressListener; public class LoginActivity extends DoubleClickExitActivity implements View.OnClickListener, IAuthenticateView, ILoginView, IQrCodeDataView, IFaceLoginView { @@ -56,8 +70,6 @@ QMUIRoundButton loginButton; @BindView(R.id.rememberPasswordView) CheckBox rememberPasswordView; - @BindView(R.id.changeLoginModeView) - TextView changeLoginModeView; private QMUITipDialog loadingDialog; private AuthenticatePresenterImpl authenticatePresenter; @@ -130,7 +142,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } else { @@ -146,7 +158,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } @@ -156,6 +168,55 @@ } } + private void captureFaceData() { + //TODO 调相机,捕获人脸数据,并保存为文件得到路径 + PictureSelector.create(this) + .openCamera(PictureMimeType.ofImage()) + .imageEngine(GlideLoadEngine.createGlideEngine()) + .maxSelectNum(1) + .forResult(PictureConfig.REQUEST_CAMERA); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + if (requestCode == PictureConfig.REQUEST_CAMERA) { + LocalMedia localMedia = PictureSelector.obtainMultipleResult(data).get(0); + Luban.with(this) + .load(localMedia.getRealPath()) + .ignoreBy(100) + .setTargetDir(FileUtils.getFileDir("CompressImageFile")) + .filter(new CompressionPredicate() { + @Override + public boolean apply(String path) { + return !(TextUtils.isEmpty(path) || path.toLowerCase().endsWith(".gif")); + } + }) + .setCompressListener(new OnCompressListener() { + @Override + public void onStart() { + // TODO 压缩开始前调用,可以在方法内启动 loading UI + } + + @Override + public void onSuccess(File file) { + String imageToBase64 = StringHelper.imageToBase64(file); + + ImageBean imageBean = new ImageBean(); + imageBean.setImage(imageToBase64); + faceLoginPresenter.onReadyRetrofitRequest(imageBean); + } + + @Override + public void onError(Throwable e) { + // TODO 当压缩过程出现问题时调用 + } + }).launch(); + } + } + } + private void startScannerLogin() { QrConfig qrConfig = new QrConfig.Builder() .setTitleText("扫码登录")//设置Title文字 @@ -193,7 +254,7 @@ @Override public void authenticateResult(PublicKeyBean result) { -// Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); + Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); if (result.isSuccess()) { PublicKey publicKey = RSAUtils.keyStrToPublicKey(result.getData().getPublicKey()); if (TextUtils.isEmpty(userName)) { @@ -240,12 +301,22 @@ //验证成功登录 startActivity(new Intent(this, MainActivity.class)); finish(); + } else { + Toast.makeText(this, "二维码已失效", Toast.LENGTH_SHORT).show(); } } @Override public void obtainFaceLoginData(FaceLoginResultBean resultBean) { - +// Log.d(TAG, "obtainFaceLoginData: " + new Gson().toJson(resultBean)); + if (resultBean.getCode() == 200) { + TokenHelper.saveToken(resultBean.getData().getToken()); + //验证成功登录 + startActivity(new Intent(this, MainActivity.class)); + finish(); + } else { + Toast.makeText(this, "无法解析人脸", Toast.LENGTH_SHORT).show(); + } } @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java index 4baf176..f70848a 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java @@ -3,14 +3,14 @@ import androidx.core.content.ContextCompat; import com.casic.birmm.hxrq.R; -import com.casic.birmm.hxrq.base.BaseActivity; +import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.utils.SaveKeyValues; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.QMUITopBarLayout; import butterknife.BindView; -public class MainActivity extends BaseActivity { +public class MainActivity extends DoubleClickExitActivity { @BindView(R.id.mainTopLayout) QMUITopBarLayout mainTopLayout; diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java b/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java new file mode 100644 index 0000000..fc939a7 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java @@ -0,0 +1,34 @@ +package com.casic.birmm.hxrq.utils; + +import android.os.Environment; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +public class FileUtils { + + public static String getFileDir(String dirName) { + File imageDir = new File(Environment.getExternalStorageDirectory(), dirName); + if (!imageDir.exists()) { + imageDir.mkdir(); + } + return imageDir.toString(); + } + + public static File getFaceImageFile() { + String imageDir = getFileDir("FaceImageFile"); + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date()); + File imageFile = new File(imageDir + File.separator + "IMG_" + timeStamp + ".png"); + if (!imageFile.exists()) { + try { + imageFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return imageFile; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java b/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java new file mode 100644 index 0000000..6de07df --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java @@ -0,0 +1,89 @@ +package com.casic.birmm.hxrq.utils; + +import android.content.Context; +import android.graphics.Bitmap; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.core.graphics.drawable.RoundedBitmapDrawable; +import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; +import com.bumptech.glide.request.target.BitmapImageViewTarget; +import com.casic.birmm.hxrq.R; +import com.luck.picture.lib.engine.ImageEngine; +import com.luck.picture.lib.listener.OnImageCompleteCallback; +import com.luck.picture.lib.widget.longimage.SubsamplingScaleImageView; + +/** + * @Author: Pengxh + * @Time: 2021/4/7 15:54 + * @Emain: 290677893@qq.com + **/ +public class GlideLoadEngine implements ImageEngine { + + private GlideLoadEngine() { + + } + + private static GlideLoadEngine instance; + + public static GlideLoadEngine createGlideEngine() { + if (null == instance) { + synchronized (GlideLoadEngine.class) { + if (null == instance) { + instance = new GlideLoadEngine(); + } + } + } + return instance; + } + + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context).load(url).into(imageView); + } + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView, SubsamplingScaleImageView longImageView, OnImageCompleteCallback callback) { + + } + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView, SubsamplingScaleImageView longImageView) { + + } + + @Override + public void loadFolderImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context) + .asBitmap() + .load(url) + .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder)) + .into(new BitmapImageViewTarget(imageView) { + @Override + protected void setResource(Bitmap resource) { + RoundedBitmapDrawable circularBitmapDrawable = + RoundedBitmapDrawableFactory. + create(context.getResources(), resource); + circularBitmapDrawable.setCornerRadius(8); + imageView.setImageDrawable(circularBitmapDrawable); + } + }); + } + + @Override + public void loadAsGifImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context).asGif().load(url).into(imageView); + } + + @Override + public void loadGridImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context) + .load(url) + .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder)) + .into(imageView); + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java b/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java deleted file mode 100644 index 065eab3..0000000 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.casic.birmm.hxrq.utils; - -import android.util.Log; - -import com.casic.birmm.hxrq.utils.callback.ILoginResultListener; - -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; - -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import rx.Observable; -import rx.Subscriber; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; - -public class HttpHelper { - private static final String TAG = "HttpHelper"; - - public static void loginWithPassword(String url, String userName, String password, ILoginResultListener listener) { - Observable.create((Observable.OnSubscribe) subscriber -> - new OkHttpClient().newCall(new Request.Builder() - .url("http://111.198.10.15:20403/cockpit/mrg/login/") - .get() - .build()) - .enqueue(new Callback() { - @Override - public void onFailure(@NotNull Call call, @NotNull IOException e) { - subscriber.onError(e); - } - - @Override - public void onResponse(@NotNull Call call, @NotNull Response response) { - subscriber.onNext(response); - } - })).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber() { - @Override - public void onError(Throwable e) { - Log.d(TAG, "onError: " + e); - } - - @Override - public void onNext(Response response) { - if (response == null) { - Log.e(TAG, "请求出错: ", new NullPointerException()); - return; - } - try { - Log.d(TAG, "onNext: " + response.body().string()); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void onCompleted() { - Log.d(TAG, "onCompleted: 请求完成"); - } - }); - } -} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java b/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java index ec7bdb6..0ebf16a 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java @@ -1,5 +1,11 @@ package com.casic.birmm.hxrq.utils; +import android.util.Base64; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; + /** * @Author: Pengxh * @Time: 2021/4/9 15:12 @@ -8,6 +14,28 @@ public class StringHelper { /** * 获取图片base64编码 - * */ + */ + public static String imageToBase64(File file) { + if (file == null) { + return null; + } + try { + FileInputStream fis = new FileInputStream(file); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + byte[] b = new byte[1024]; + int n; + while ((n = fis.read(b)) != -1) { + bos.write(b, 0, n); + } + fis.close(); + bos.close(); + byte[] imgBytes = bos.toByteArray(); + String s = Base64.encodeToString(imgBytes, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING); + return s.replace("-", "+") + .replace("_", "/"); + } catch (Exception e) { + return null; + } + } } diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/callback/ILoginResultListener.java b/app/src/main/java/com/casic/birmm/hxrq/utils/callback/ILoginResultListener.java deleted file mode 100644 index b292c97..0000000 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/callback/ILoginResultListener.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.casic.birmm.hxrq.utils.callback; - -public interface ILoginResultListener { - void onLoginIn(); -} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitService.java b/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitService.java index 067e020..8fe5264 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitService.java +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitService.java @@ -1,14 +1,17 @@ package com.casic.birmm.hxrq.utils.retrofit; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.bean.LoginResultBean; import com.casic.birmm.hxrq.bean.PublicKeyBean; import com.casic.birmm.hxrq.bean.QrCodeBean; +import retrofit2.http.Body; import retrofit2.http.Field; import retrofit2.http.FormUrlEncoded; import retrofit2.http.GET; import retrofit2.http.Header; +import retrofit2.http.Headers; import retrofit2.http.POST; import retrofit2.http.Query; import rx.Observable; @@ -41,8 +44,11 @@ @Header("token") String token, @Query("qrcodeId") String qrcodeId); - @FormUrlEncoded + /** + * 人脸登录 + */ + @Headers({"Content-Type: application/json"}) @POST("/cockpit/face/login") Observable getFaceLoginResult( - @Field("image") String image); + @Body ImageBean imageBean); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitServiceManager.java b/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitServiceManager.java index 590bd91..ef4307e 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitServiceManager.java +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitServiceManager.java @@ -3,12 +3,14 @@ import android.util.Log; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.bean.LoginResultBean; import com.casic.birmm.hxrq.bean.PublicKeyBean; import com.casic.birmm.hxrq.bean.QrCodeBean; import com.casic.birmm.hxrq.utils.HttpConfig; import org.jetbrains.annotations.NotNull; +import org.json.JSONObject; import java.util.concurrent.TimeUnit; @@ -77,9 +79,9 @@ /** * 人脸识别登录结果 */ - public static Observable getFaceResult(String baseUrl, String image) { + public static Observable getFaceResult(String baseUrl, ImageBean imageBean) { Retrofit retrofit = createRetrofit(baseUrl); RetrofitService service = retrofit.create(RetrofitService.class); - return service.getFaceLoginResult(image); + return service.getFaceLoginResult(imageBean); } } diff --git a/app/src/main/res/xml/filepaths.xml b/app/src/main/res/xml/filepaths.xml new file mode 100644 index 0000000..fafa14f --- /dev/null +++ b/app/src/main/res/xml/filepaths.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index f98f5bc..9d60011 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,4 +56,10 @@ implementation 'com.google.code.gson:gson:2.8.6' //ZBar扫一扫 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' + //图片选择框架 + implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.5.0' + //图片压缩框架 + implementation 'top.zibin:Luban:1.1.8' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2b7b378..c6065dc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/QMUI.Compat.NoActionBar" @@ -29,6 +30,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java new file mode 100644 index 0000000..e685c07 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java @@ -0,0 +1,18 @@ +package com.casic.birmm.hxrq.bean; + +/** + * @Author: Pengxh + * @Time: 2021/4/9 19:00 + * @Email: 290677893@qq.com + **/ +public class ImageBean { + private String image; + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java index 06c0332..d8b2ab7 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.model; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.utils.HttpConfig; import com.casic.birmm.hxrq.utils.retrofit.RetrofitServiceManager; @@ -33,7 +34,7 @@ } @Override - public Subscription sendRetrofitRequest(String image) { + public Subscription sendRetrofitRequest(ImageBean image) { Observable observable = RetrofitServiceManager.getFaceResult(HttpConfig.BASE_IP, image); return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer() { @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java index 5a14fee..c63312c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java @@ -1,8 +1,9 @@ package com.casic.birmm.hxrq.mvp.model; +import com.casic.birmm.hxrq.bean.ImageBean; + import rx.Subscription; public interface IFaceLoginModel { - //image传的是图片的base64编码 - Subscription sendRetrofitRequest(String image); + Subscription sendRetrofitRequest(ImageBean image); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java index 51e4f4f..7fb154c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.presenter; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.mvp.BasePresenter; import com.casic.birmm.hxrq.mvp.model.FaceLoginModelImpl; import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; @@ -21,7 +22,7 @@ } @Override - public void onReadyRetrofitRequest(String image) { + public void onReadyRetrofitRequest(ImageBean image) { addSubscription(actionModel.sendRetrofitRequest(image)); } @@ -30,6 +31,7 @@ unSubscription(); } + @Override public void onSuccess(FaceLoginResultBean resultBean) { view.obtainFaceLoginData(resultBean); diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java index f525a45..01a5512 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java @@ -1,12 +1,14 @@ package com.casic.birmm.hxrq.mvp.presenter; +import com.casic.birmm.hxrq.bean.ImageBean; + /** * @Author: Pengxh * @Time: 2021/4/9 14:55 * @Email: 290677893@qq.com **/ public interface IFaceLoginPresenter { - void onReadyRetrofitRequest(String image); + void onReadyRetrofitRequest(ImageBean image); void disposeRetrofitRequest(); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java index e9f01ce..98aef9d 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java @@ -9,12 +9,14 @@ import android.view.View; import android.widget.CheckBox; import android.widget.EditText; -import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.Nullable; + import com.casic.birmm.hxrq.R; import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.bean.LoginResultBean; import com.casic.birmm.hxrq.bean.PublicKeyBean; import com.casic.birmm.hxrq.bean.QrCodeBean; @@ -26,14 +28,23 @@ import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; import com.casic.birmm.hxrq.mvp.view.ILoginView; import com.casic.birmm.hxrq.mvp.view.IQrCodeDataView; +import com.casic.birmm.hxrq.utils.FileUtils; +import com.casic.birmm.hxrq.utils.GlideLoadEngine; import com.casic.birmm.hxrq.utils.RSAUtils; import com.casic.birmm.hxrq.utils.SaveKeyValues; +import com.casic.birmm.hxrq.utils.StringHelper; import com.casic.birmm.hxrq.utils.TokenHelper; +import com.google.gson.Gson; +import com.luck.picture.lib.PictureSelector; +import com.luck.picture.lib.config.PictureConfig; +import com.luck.picture.lib.config.PictureMimeType; +import com.luck.picture.lib.entity.LocalMedia; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.dialog.QMUIDialog; import com.qmuiteam.qmui.widget.dialog.QMUITipDialog; import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton; +import java.io.File; import java.security.PublicKey; import butterknife.BindView; @@ -42,6 +53,9 @@ import cn.bertsir.zbar.QrConfig; import cn.bertsir.zbar.QrManager; import cn.bertsir.zbar.view.ScanLineView; +import top.zibin.luban.CompressionPredicate; +import top.zibin.luban.Luban; +import top.zibin.luban.OnCompressListener; public class LoginActivity extends DoubleClickExitActivity implements View.OnClickListener, IAuthenticateView, ILoginView, IQrCodeDataView, IFaceLoginView { @@ -56,8 +70,6 @@ QMUIRoundButton loginButton; @BindView(R.id.rememberPasswordView) CheckBox rememberPasswordView; - @BindView(R.id.changeLoginModeView) - TextView changeLoginModeView; private QMUITipDialog loadingDialog; private AuthenticatePresenterImpl authenticatePresenter; @@ -130,7 +142,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } else { @@ -146,7 +158,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } @@ -156,6 +168,55 @@ } } + private void captureFaceData() { + //TODO 调相机,捕获人脸数据,并保存为文件得到路径 + PictureSelector.create(this) + .openCamera(PictureMimeType.ofImage()) + .imageEngine(GlideLoadEngine.createGlideEngine()) + .maxSelectNum(1) + .forResult(PictureConfig.REQUEST_CAMERA); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + if (requestCode == PictureConfig.REQUEST_CAMERA) { + LocalMedia localMedia = PictureSelector.obtainMultipleResult(data).get(0); + Luban.with(this) + .load(localMedia.getRealPath()) + .ignoreBy(100) + .setTargetDir(FileUtils.getFileDir("CompressImageFile")) + .filter(new CompressionPredicate() { + @Override + public boolean apply(String path) { + return !(TextUtils.isEmpty(path) || path.toLowerCase().endsWith(".gif")); + } + }) + .setCompressListener(new OnCompressListener() { + @Override + public void onStart() { + // TODO 压缩开始前调用,可以在方法内启动 loading UI + } + + @Override + public void onSuccess(File file) { + String imageToBase64 = StringHelper.imageToBase64(file); + + ImageBean imageBean = new ImageBean(); + imageBean.setImage(imageToBase64); + faceLoginPresenter.onReadyRetrofitRequest(imageBean); + } + + @Override + public void onError(Throwable e) { + // TODO 当压缩过程出现问题时调用 + } + }).launch(); + } + } + } + private void startScannerLogin() { QrConfig qrConfig = new QrConfig.Builder() .setTitleText("扫码登录")//设置Title文字 @@ -193,7 +254,7 @@ @Override public void authenticateResult(PublicKeyBean result) { -// Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); + Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); if (result.isSuccess()) { PublicKey publicKey = RSAUtils.keyStrToPublicKey(result.getData().getPublicKey()); if (TextUtils.isEmpty(userName)) { @@ -240,12 +301,22 @@ //验证成功登录 startActivity(new Intent(this, MainActivity.class)); finish(); + } else { + Toast.makeText(this, "二维码已失效", Toast.LENGTH_SHORT).show(); } } @Override public void obtainFaceLoginData(FaceLoginResultBean resultBean) { - +// Log.d(TAG, "obtainFaceLoginData: " + new Gson().toJson(resultBean)); + if (resultBean.getCode() == 200) { + TokenHelper.saveToken(resultBean.getData().getToken()); + //验证成功登录 + startActivity(new Intent(this, MainActivity.class)); + finish(); + } else { + Toast.makeText(this, "无法解析人脸", Toast.LENGTH_SHORT).show(); + } } @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java index 4baf176..f70848a 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java @@ -3,14 +3,14 @@ import androidx.core.content.ContextCompat; import com.casic.birmm.hxrq.R; -import com.casic.birmm.hxrq.base.BaseActivity; +import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.utils.SaveKeyValues; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.QMUITopBarLayout; import butterknife.BindView; -public class MainActivity extends BaseActivity { +public class MainActivity extends DoubleClickExitActivity { @BindView(R.id.mainTopLayout) QMUITopBarLayout mainTopLayout; diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java b/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java new file mode 100644 index 0000000..fc939a7 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java @@ -0,0 +1,34 @@ +package com.casic.birmm.hxrq.utils; + +import android.os.Environment; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +public class FileUtils { + + public static String getFileDir(String dirName) { + File imageDir = new File(Environment.getExternalStorageDirectory(), dirName); + if (!imageDir.exists()) { + imageDir.mkdir(); + } + return imageDir.toString(); + } + + public static File getFaceImageFile() { + String imageDir = getFileDir("FaceImageFile"); + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date()); + File imageFile = new File(imageDir + File.separator + "IMG_" + timeStamp + ".png"); + if (!imageFile.exists()) { + try { + imageFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return imageFile; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java b/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java new file mode 100644 index 0000000..6de07df --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java @@ -0,0 +1,89 @@ +package com.casic.birmm.hxrq.utils; + +import android.content.Context; +import android.graphics.Bitmap; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.core.graphics.drawable.RoundedBitmapDrawable; +import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; +import com.bumptech.glide.request.target.BitmapImageViewTarget; +import com.casic.birmm.hxrq.R; +import com.luck.picture.lib.engine.ImageEngine; +import com.luck.picture.lib.listener.OnImageCompleteCallback; +import com.luck.picture.lib.widget.longimage.SubsamplingScaleImageView; + +/** + * @Author: Pengxh + * @Time: 2021/4/7 15:54 + * @Emain: 290677893@qq.com + **/ +public class GlideLoadEngine implements ImageEngine { + + private GlideLoadEngine() { + + } + + private static GlideLoadEngine instance; + + public static GlideLoadEngine createGlideEngine() { + if (null == instance) { + synchronized (GlideLoadEngine.class) { + if (null == instance) { + instance = new GlideLoadEngine(); + } + } + } + return instance; + } + + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context).load(url).into(imageView); + } + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView, SubsamplingScaleImageView longImageView, OnImageCompleteCallback callback) { + + } + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView, SubsamplingScaleImageView longImageView) { + + } + + @Override + public void loadFolderImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context) + .asBitmap() + .load(url) + .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder)) + .into(new BitmapImageViewTarget(imageView) { + @Override + protected void setResource(Bitmap resource) { + RoundedBitmapDrawable circularBitmapDrawable = + RoundedBitmapDrawableFactory. + create(context.getResources(), resource); + circularBitmapDrawable.setCornerRadius(8); + imageView.setImageDrawable(circularBitmapDrawable); + } + }); + } + + @Override + public void loadAsGifImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context).asGif().load(url).into(imageView); + } + + @Override + public void loadGridImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context) + .load(url) + .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder)) + .into(imageView); + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java b/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java deleted file mode 100644 index 065eab3..0000000 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.casic.birmm.hxrq.utils; - -import android.util.Log; - -import com.casic.birmm.hxrq.utils.callback.ILoginResultListener; - -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; - -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import rx.Observable; -import rx.Subscriber; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; - -public class HttpHelper { - private static final String TAG = "HttpHelper"; - - public static void loginWithPassword(String url, String userName, String password, ILoginResultListener listener) { - Observable.create((Observable.OnSubscribe) subscriber -> - new OkHttpClient().newCall(new Request.Builder() - .url("http://111.198.10.15:20403/cockpit/mrg/login/") - .get() - .build()) - .enqueue(new Callback() { - @Override - public void onFailure(@NotNull Call call, @NotNull IOException e) { - subscriber.onError(e); - } - - @Override - public void onResponse(@NotNull Call call, @NotNull Response response) { - subscriber.onNext(response); - } - })).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber() { - @Override - public void onError(Throwable e) { - Log.d(TAG, "onError: " + e); - } - - @Override - public void onNext(Response response) { - if (response == null) { - Log.e(TAG, "请求出错: ", new NullPointerException()); - return; - } - try { - Log.d(TAG, "onNext: " + response.body().string()); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void onCompleted() { - Log.d(TAG, "onCompleted: 请求完成"); - } - }); - } -} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java b/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java index ec7bdb6..0ebf16a 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java @@ -1,5 +1,11 @@ package com.casic.birmm.hxrq.utils; +import android.util.Base64; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; + /** * @Author: Pengxh * @Time: 2021/4/9 15:12 @@ -8,6 +14,28 @@ public class StringHelper { /** * 获取图片base64编码 - * */ + */ + public static String imageToBase64(File file) { + if (file == null) { + return null; + } + try { + FileInputStream fis = new FileInputStream(file); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + byte[] b = new byte[1024]; + int n; + while ((n = fis.read(b)) != -1) { + bos.write(b, 0, n); + } + fis.close(); + bos.close(); + byte[] imgBytes = bos.toByteArray(); + String s = Base64.encodeToString(imgBytes, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING); + return s.replace("-", "+") + .replace("_", "/"); + } catch (Exception e) { + return null; + } + } } diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/callback/ILoginResultListener.java b/app/src/main/java/com/casic/birmm/hxrq/utils/callback/ILoginResultListener.java deleted file mode 100644 index b292c97..0000000 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/callback/ILoginResultListener.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.casic.birmm.hxrq.utils.callback; - -public interface ILoginResultListener { - void onLoginIn(); -} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitService.java b/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitService.java index 067e020..8fe5264 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitService.java +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitService.java @@ -1,14 +1,17 @@ package com.casic.birmm.hxrq.utils.retrofit; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.bean.LoginResultBean; import com.casic.birmm.hxrq.bean.PublicKeyBean; import com.casic.birmm.hxrq.bean.QrCodeBean; +import retrofit2.http.Body; import retrofit2.http.Field; import retrofit2.http.FormUrlEncoded; import retrofit2.http.GET; import retrofit2.http.Header; +import retrofit2.http.Headers; import retrofit2.http.POST; import retrofit2.http.Query; import rx.Observable; @@ -41,8 +44,11 @@ @Header("token") String token, @Query("qrcodeId") String qrcodeId); - @FormUrlEncoded + /** + * 人脸登录 + */ + @Headers({"Content-Type: application/json"}) @POST("/cockpit/face/login") Observable getFaceLoginResult( - @Field("image") String image); + @Body ImageBean imageBean); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitServiceManager.java b/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitServiceManager.java index 590bd91..ef4307e 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitServiceManager.java +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitServiceManager.java @@ -3,12 +3,14 @@ import android.util.Log; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.bean.LoginResultBean; import com.casic.birmm.hxrq.bean.PublicKeyBean; import com.casic.birmm.hxrq.bean.QrCodeBean; import com.casic.birmm.hxrq.utils.HttpConfig; import org.jetbrains.annotations.NotNull; +import org.json.JSONObject; import java.util.concurrent.TimeUnit; @@ -77,9 +79,9 @@ /** * 人脸识别登录结果 */ - public static Observable getFaceResult(String baseUrl, String image) { + public static Observable getFaceResult(String baseUrl, ImageBean imageBean) { Retrofit retrofit = createRetrofit(baseUrl); RetrofitService service = retrofit.create(RetrofitService.class); - return service.getFaceLoginResult(image); + return service.getFaceLoginResult(imageBean); } } diff --git a/app/src/main/res/xml/filepaths.xml b/app/src/main/res/xml/filepaths.xml new file mode 100644 index 0000000..fafa14f --- /dev/null +++ b/app/src/main/res/xml/filepaths.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 5aaf0ce..30793d4 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } google() jcenter() - + maven { url 'https://jitpack.io' } } } diff --git a/app/build.gradle b/app/build.gradle index f98f5bc..9d60011 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,4 +56,10 @@ implementation 'com.google.code.gson:gson:2.8.6' //ZBar扫一扫 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' + //图片选择框架 + implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.5.0' + //图片压缩框架 + implementation 'top.zibin:Luban:1.1.8' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2b7b378..c6065dc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/QMUI.Compat.NoActionBar" @@ -29,6 +30,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java new file mode 100644 index 0000000..e685c07 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/bean/ImageBean.java @@ -0,0 +1,18 @@ +package com.casic.birmm.hxrq.bean; + +/** + * @Author: Pengxh + * @Time: 2021/4/9 19:00 + * @Email: 290677893@qq.com + **/ +public class ImageBean { + private String image; + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java index 06c0332..d8b2ab7 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/FaceLoginModelImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.model; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.utils.HttpConfig; import com.casic.birmm.hxrq.utils.retrofit.RetrofitServiceManager; @@ -33,7 +34,7 @@ } @Override - public Subscription sendRetrofitRequest(String image) { + public Subscription sendRetrofitRequest(ImageBean image) { Observable observable = RetrofitServiceManager.getFaceResult(HttpConfig.BASE_IP, image); return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer() { @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java index 5a14fee..c63312c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/model/IFaceLoginModel.java @@ -1,8 +1,9 @@ package com.casic.birmm.hxrq.mvp.model; +import com.casic.birmm.hxrq.bean.ImageBean; + import rx.Subscription; public interface IFaceLoginModel { - //image传的是图片的base64编码 - Subscription sendRetrofitRequest(String image); + Subscription sendRetrofitRequest(ImageBean image); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java index 51e4f4f..7fb154c 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/FaceLoginPresenterImpl.java @@ -1,6 +1,7 @@ package com.casic.birmm.hxrq.mvp.presenter; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.mvp.BasePresenter; import com.casic.birmm.hxrq.mvp.model.FaceLoginModelImpl; import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; @@ -21,7 +22,7 @@ } @Override - public void onReadyRetrofitRequest(String image) { + public void onReadyRetrofitRequest(ImageBean image) { addSubscription(actionModel.sendRetrofitRequest(image)); } @@ -30,6 +31,7 @@ unSubscription(); } + @Override public void onSuccess(FaceLoginResultBean resultBean) { view.obtainFaceLoginData(resultBean); diff --git a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java index f525a45..01a5512 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java +++ b/app/src/main/java/com/casic/birmm/hxrq/mvp/presenter/IFaceLoginPresenter.java @@ -1,12 +1,14 @@ package com.casic.birmm.hxrq.mvp.presenter; +import com.casic.birmm.hxrq.bean.ImageBean; + /** * @Author: Pengxh * @Time: 2021/4/9 14:55 * @Email: 290677893@qq.com **/ public interface IFaceLoginPresenter { - void onReadyRetrofitRequest(String image); + void onReadyRetrofitRequest(ImageBean image); void disposeRetrofitRequest(); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java index e9f01ce..98aef9d 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/LoginActivity.java @@ -9,12 +9,14 @@ import android.view.View; import android.widget.CheckBox; import android.widget.EditText; -import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.Nullable; + import com.casic.birmm.hxrq.R; import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.bean.LoginResultBean; import com.casic.birmm.hxrq.bean.PublicKeyBean; import com.casic.birmm.hxrq.bean.QrCodeBean; @@ -26,14 +28,23 @@ import com.casic.birmm.hxrq.mvp.view.IFaceLoginView; import com.casic.birmm.hxrq.mvp.view.ILoginView; import com.casic.birmm.hxrq.mvp.view.IQrCodeDataView; +import com.casic.birmm.hxrq.utils.FileUtils; +import com.casic.birmm.hxrq.utils.GlideLoadEngine; import com.casic.birmm.hxrq.utils.RSAUtils; import com.casic.birmm.hxrq.utils.SaveKeyValues; +import com.casic.birmm.hxrq.utils.StringHelper; import com.casic.birmm.hxrq.utils.TokenHelper; +import com.google.gson.Gson; +import com.luck.picture.lib.PictureSelector; +import com.luck.picture.lib.config.PictureConfig; +import com.luck.picture.lib.config.PictureMimeType; +import com.luck.picture.lib.entity.LocalMedia; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.dialog.QMUIDialog; import com.qmuiteam.qmui.widget.dialog.QMUITipDialog; import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton; +import java.io.File; import java.security.PublicKey; import butterknife.BindView; @@ -42,6 +53,9 @@ import cn.bertsir.zbar.QrConfig; import cn.bertsir.zbar.QrManager; import cn.bertsir.zbar.view.ScanLineView; +import top.zibin.luban.CompressionPredicate; +import top.zibin.luban.Luban; +import top.zibin.luban.OnCompressListener; public class LoginActivity extends DoubleClickExitActivity implements View.OnClickListener, IAuthenticateView, ILoginView, IQrCodeDataView, IFaceLoginView { @@ -56,8 +70,6 @@ QMUIRoundButton loginButton; @BindView(R.id.rememberPasswordView) CheckBox rememberPasswordView; - @BindView(R.id.changeLoginModeView) - TextView changeLoginModeView; private QMUITipDialog loadingDialog; private AuthenticatePresenterImpl authenticatePresenter; @@ -130,7 +142,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } else { @@ -146,7 +158,7 @@ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); -// faceLoginPresenter.onReadyRetrofitRequest(); + captureFaceData(); } }).create().show(); } @@ -156,6 +168,55 @@ } } + private void captureFaceData() { + //TODO 调相机,捕获人脸数据,并保存为文件得到路径 + PictureSelector.create(this) + .openCamera(PictureMimeType.ofImage()) + .imageEngine(GlideLoadEngine.createGlideEngine()) + .maxSelectNum(1) + .forResult(PictureConfig.REQUEST_CAMERA); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + if (requestCode == PictureConfig.REQUEST_CAMERA) { + LocalMedia localMedia = PictureSelector.obtainMultipleResult(data).get(0); + Luban.with(this) + .load(localMedia.getRealPath()) + .ignoreBy(100) + .setTargetDir(FileUtils.getFileDir("CompressImageFile")) + .filter(new CompressionPredicate() { + @Override + public boolean apply(String path) { + return !(TextUtils.isEmpty(path) || path.toLowerCase().endsWith(".gif")); + } + }) + .setCompressListener(new OnCompressListener() { + @Override + public void onStart() { + // TODO 压缩开始前调用,可以在方法内启动 loading UI + } + + @Override + public void onSuccess(File file) { + String imageToBase64 = StringHelper.imageToBase64(file); + + ImageBean imageBean = new ImageBean(); + imageBean.setImage(imageToBase64); + faceLoginPresenter.onReadyRetrofitRequest(imageBean); + } + + @Override + public void onError(Throwable e) { + // TODO 当压缩过程出现问题时调用 + } + }).launch(); + } + } + } + private void startScannerLogin() { QrConfig qrConfig = new QrConfig.Builder() .setTitleText("扫码登录")//设置Title文字 @@ -193,7 +254,7 @@ @Override public void authenticateResult(PublicKeyBean result) { -// Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); + Log.d(TAG, "authenticateResult: " + new Gson().toJson(result)); if (result.isSuccess()) { PublicKey publicKey = RSAUtils.keyStrToPublicKey(result.getData().getPublicKey()); if (TextUtils.isEmpty(userName)) { @@ -240,12 +301,22 @@ //验证成功登录 startActivity(new Intent(this, MainActivity.class)); finish(); + } else { + Toast.makeText(this, "二维码已失效", Toast.LENGTH_SHORT).show(); } } @Override public void obtainFaceLoginData(FaceLoginResultBean resultBean) { - +// Log.d(TAG, "obtainFaceLoginData: " + new Gson().toJson(resultBean)); + if (resultBean.getCode() == 200) { + TokenHelper.saveToken(resultBean.getData().getToken()); + //验证成功登录 + startActivity(new Intent(this, MainActivity.class)); + finish(); + } else { + Toast.makeText(this, "无法解析人脸", Toast.LENGTH_SHORT).show(); + } } @Override diff --git a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java index 4baf176..f70848a 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java +++ b/app/src/main/java/com/casic/birmm/hxrq/ui/MainActivity.java @@ -3,14 +3,14 @@ import androidx.core.content.ContextCompat; import com.casic.birmm.hxrq.R; -import com.casic.birmm.hxrq.base.BaseActivity; +import com.casic.birmm.hxrq.base.DoubleClickExitActivity; import com.casic.birmm.hxrq.utils.SaveKeyValues; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; import com.qmuiteam.qmui.widget.QMUITopBarLayout; import butterknife.BindView; -public class MainActivity extends BaseActivity { +public class MainActivity extends DoubleClickExitActivity { @BindView(R.id.mainTopLayout) QMUITopBarLayout mainTopLayout; diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java b/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java new file mode 100644 index 0000000..fc939a7 --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/FileUtils.java @@ -0,0 +1,34 @@ +package com.casic.birmm.hxrq.utils; + +import android.os.Environment; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +public class FileUtils { + + public static String getFileDir(String dirName) { + File imageDir = new File(Environment.getExternalStorageDirectory(), dirName); + if (!imageDir.exists()) { + imageDir.mkdir(); + } + return imageDir.toString(); + } + + public static File getFaceImageFile() { + String imageDir = getFileDir("FaceImageFile"); + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date()); + File imageFile = new File(imageDir + File.separator + "IMG_" + timeStamp + ".png"); + if (!imageFile.exists()) { + try { + imageFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return imageFile; + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java b/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java new file mode 100644 index 0000000..6de07df --- /dev/null +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/GlideLoadEngine.java @@ -0,0 +1,89 @@ +package com.casic.birmm.hxrq.utils; + +import android.content.Context; +import android.graphics.Bitmap; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.core.graphics.drawable.RoundedBitmapDrawable; +import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; +import com.bumptech.glide.request.target.BitmapImageViewTarget; +import com.casic.birmm.hxrq.R; +import com.luck.picture.lib.engine.ImageEngine; +import com.luck.picture.lib.listener.OnImageCompleteCallback; +import com.luck.picture.lib.widget.longimage.SubsamplingScaleImageView; + +/** + * @Author: Pengxh + * @Time: 2021/4/7 15:54 + * @Emain: 290677893@qq.com + **/ +public class GlideLoadEngine implements ImageEngine { + + private GlideLoadEngine() { + + } + + private static GlideLoadEngine instance; + + public static GlideLoadEngine createGlideEngine() { + if (null == instance) { + synchronized (GlideLoadEngine.class) { + if (null == instance) { + instance = new GlideLoadEngine(); + } + } + } + return instance; + } + + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context).load(url).into(imageView); + } + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView, SubsamplingScaleImageView longImageView, OnImageCompleteCallback callback) { + + } + + @Override + public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView, SubsamplingScaleImageView longImageView) { + + } + + @Override + public void loadFolderImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context) + .asBitmap() + .load(url) + .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder)) + .into(new BitmapImageViewTarget(imageView) { + @Override + protected void setResource(Bitmap resource) { + RoundedBitmapDrawable circularBitmapDrawable = + RoundedBitmapDrawableFactory. + create(context.getResources(), resource); + circularBitmapDrawable.setCornerRadius(8); + imageView.setImageDrawable(circularBitmapDrawable); + } + }); + } + + @Override + public void loadAsGifImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context).asGif().load(url).into(imageView); + } + + @Override + public void loadGridImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) { + Glide.with(context) + .load(url) + .apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder)) + .into(imageView); + } +} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java b/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java deleted file mode 100644 index 065eab3..0000000 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/HttpHelper.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.casic.birmm.hxrq.utils; - -import android.util.Log; - -import com.casic.birmm.hxrq.utils.callback.ILoginResultListener; - -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; - -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import rx.Observable; -import rx.Subscriber; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; - -public class HttpHelper { - private static final String TAG = "HttpHelper"; - - public static void loginWithPassword(String url, String userName, String password, ILoginResultListener listener) { - Observable.create((Observable.OnSubscribe) subscriber -> - new OkHttpClient().newCall(new Request.Builder() - .url("http://111.198.10.15:20403/cockpit/mrg/login/") - .get() - .build()) - .enqueue(new Callback() { - @Override - public void onFailure(@NotNull Call call, @NotNull IOException e) { - subscriber.onError(e); - } - - @Override - public void onResponse(@NotNull Call call, @NotNull Response response) { - subscriber.onNext(response); - } - })).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber() { - @Override - public void onError(Throwable e) { - Log.d(TAG, "onError: " + e); - } - - @Override - public void onNext(Response response) { - if (response == null) { - Log.e(TAG, "请求出错: ", new NullPointerException()); - return; - } - try { - Log.d(TAG, "onNext: " + response.body().string()); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void onCompleted() { - Log.d(TAG, "onCompleted: 请求完成"); - } - }); - } -} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java b/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java index ec7bdb6..0ebf16a 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/StringHelper.java @@ -1,5 +1,11 @@ package com.casic.birmm.hxrq.utils; +import android.util.Base64; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; + /** * @Author: Pengxh * @Time: 2021/4/9 15:12 @@ -8,6 +14,28 @@ public class StringHelper { /** * 获取图片base64编码 - * */ + */ + public static String imageToBase64(File file) { + if (file == null) { + return null; + } + try { + FileInputStream fis = new FileInputStream(file); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + byte[] b = new byte[1024]; + int n; + while ((n = fis.read(b)) != -1) { + bos.write(b, 0, n); + } + fis.close(); + bos.close(); + byte[] imgBytes = bos.toByteArray(); + String s = Base64.encodeToString(imgBytes, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING); + return s.replace("-", "+") + .replace("_", "/"); + } catch (Exception e) { + return null; + } + } } diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/callback/ILoginResultListener.java b/app/src/main/java/com/casic/birmm/hxrq/utils/callback/ILoginResultListener.java deleted file mode 100644 index b292c97..0000000 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/callback/ILoginResultListener.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.casic.birmm.hxrq.utils.callback; - -public interface ILoginResultListener { - void onLoginIn(); -} diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitService.java b/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitService.java index 067e020..8fe5264 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitService.java +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitService.java @@ -1,14 +1,17 @@ package com.casic.birmm.hxrq.utils.retrofit; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.bean.LoginResultBean; import com.casic.birmm.hxrq.bean.PublicKeyBean; import com.casic.birmm.hxrq.bean.QrCodeBean; +import retrofit2.http.Body; import retrofit2.http.Field; import retrofit2.http.FormUrlEncoded; import retrofit2.http.GET; import retrofit2.http.Header; +import retrofit2.http.Headers; import retrofit2.http.POST; import retrofit2.http.Query; import rx.Observable; @@ -41,8 +44,11 @@ @Header("token") String token, @Query("qrcodeId") String qrcodeId); - @FormUrlEncoded + /** + * 人脸登录 + */ + @Headers({"Content-Type: application/json"}) @POST("/cockpit/face/login") Observable getFaceLoginResult( - @Field("image") String image); + @Body ImageBean imageBean); } diff --git a/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitServiceManager.java b/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitServiceManager.java index 590bd91..ef4307e 100644 --- a/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitServiceManager.java +++ b/app/src/main/java/com/casic/birmm/hxrq/utils/retrofit/RetrofitServiceManager.java @@ -3,12 +3,14 @@ import android.util.Log; import com.casic.birmm.hxrq.bean.FaceLoginResultBean; +import com.casic.birmm.hxrq.bean.ImageBean; import com.casic.birmm.hxrq.bean.LoginResultBean; import com.casic.birmm.hxrq.bean.PublicKeyBean; import com.casic.birmm.hxrq.bean.QrCodeBean; import com.casic.birmm.hxrq.utils.HttpConfig; import org.jetbrains.annotations.NotNull; +import org.json.JSONObject; import java.util.concurrent.TimeUnit; @@ -77,9 +79,9 @@ /** * 人脸识别登录结果 */ - public static Observable getFaceResult(String baseUrl, String image) { + public static Observable getFaceResult(String baseUrl, ImageBean imageBean) { Retrofit retrofit = createRetrofit(baseUrl); RetrofitService service = retrofit.create(RetrofitService.class); - return service.getFaceLoginResult(image); + return service.getFaceLoginResult(imageBean); } } diff --git a/app/src/main/res/xml/filepaths.xml b/app/src/main/res/xml/filepaths.xml new file mode 100644 index 0000000..fafa14f --- /dev/null +++ b/app/src/main/res/xml/filepaths.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 5aaf0ce..30793d4 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } google() jcenter() - + maven { url 'https://jitpack.io' } } } diff --git a/hxrq.jks b/hxrq.jks new file mode 100644 index 0000000..6910570 --- /dev/null +++ b/hxrq.jks Binary files differ