rk
5 天以前 4a8ff39b0fab0627ef8f7459587d514cc01c3676
keyCabinet-android/app/src/main/java/com/doumee/keyCabinet/ui/face/AddFaceActivity.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,604 @@
package com.doumee.keyCabinet.ui.face;
import androidx.annotation.CallSuper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.Observer;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.alibaba.fastjson.JSON;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.transition.Transition;
import com.doumee.keyCabinet.R;
import com.doumee.keyCabinet.base.MyBaseActivity;
import com.doumee.keyCabinet.bean.FaceUserBean;
import com.doumee.keyCabinet.databinding.AddFaceActivityBinding;
import com.doumee.keyCabinet.ui.face.adapter.FaceRcvAdapter;
import com.doumee.keyCabinet.ui.view.TipDialog;
import com.doumee.keyCabinet.utils.face.FaceUtils;
import com.example.datalibrary.api.FaceApi;
import com.example.datalibrary.listener.DBLoadListener;
import com.example.datalibrary.manager.FaceSDKManager;
import com.example.datalibrary.model.KeyboardsUtils;
import com.example.datalibrary.model.User;
import java.util.ArrayList;
import java.util.List;
import dagger.hilt.android.AndroidEntryPoint;
import timber.log.Timber;
@AndroidEntryPoint
public class AddFaceActivity extends MyBaseActivity<AddFaceVM, AddFaceActivityBinding>  implements View.OnClickListener,
        CompoundButton.OnCheckedChangeListener, TipDialog.OnTipDialogClickListener {
    // view
    private RecyclerView mRecyclerUserManager;
    private ImageView mImageIconSearch;        // title中的搜索按钮
    private RelativeLayout mRelativeStandard; // title中的常规布局
    private LinearLayout mLinearSearch;       // title中的搜索布局
    private boolean isCheck = false;            // title菜单点击状态
    private TextView mTextCancel;             // title中的取消按钮
    private RelativeLayout mRelativeEmpty;   // æš‚无内容
    private TextView mTextEmpty;
    private EditText mEditTitleSearch;
    private RelativeLayout mRelativeDelete;   // å¯¼å…¥äººè„¸å¸ƒå±€
    private CheckBox mCheckAll;               // å…¨é€‰
    private TextView mTextDelete;             // å¯¼å…¥äººè„¸
    private TextView textAll;
    private TipDialog mTipDialog;
    private Context mContext;
    private FaceRcvAdapter mFaceUserAdapter;
    private List<FaceUserBean> mUserInfoList;
    private int mSelectCount;                // é€‰ä¸­çš„个数
    private boolean mIsLongClick;           // æ˜¯å¦æ˜¯é•¿æŒ‰
    private ProgressBar progressBar;
    private TextView progressText;
    private View progressGroup;
    @Override
    public int getLayoutId() {
        return R.layout.add_face_activity;
    }
    @Override
    public void initView(@Nullable Bundle savedInstanceState) {
        isAddCountTimer = false;
        normalConfig();
        getDB().setModel(getVM());
        mContext = this;
        initView();
    }
    @Override
    public void initData(@Nullable Bundle savedInstanceState) {
        getVM().getDatasLD().observe(this, new Observer<List<FaceUserBean>>() {
            @Override
            public void onChanged(List<FaceUserBean> beans) {
                mUserInfoList = beans;
                if (beans == null || beans.size() == 0) {
                    mFaceUserAdapter.refreshData(new ArrayList<>());
                    mFaceUserAdapter.notifyDataSetChanged();
                    mRelativeEmpty.setVisibility(View.VISIBLE);
                    mRecyclerUserManager.setVisibility(View.GONE);
                    // æ˜¾ç¤ºæ— å†…容判断
                    if (mEditTitleSearch.getText().length()>0) {
                        mTextEmpty.setText(getString(R.string.addface_zwnr));
                        updateDeleteUI(false);
                    } else {
                        mTextEmpty.setText(getString(R.string.addface_tip1));
                        mRelativeDelete.setVisibility(View.GONE);
                    }
                    return;
                }
                // æ¢å¤é»˜è®¤çŠ¶æ€
                resetDeleteData();
                mRelativeEmpty.setVisibility(View.GONE);
                mRecyclerUserManager.setVisibility(View.VISIBLE);
                mFaceUserAdapter.refreshData(mUserInfoList);
                mFaceUserAdapter.notifyDataSetChanged();
            }
        });
        getVM().getDatas();
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        handler.removeCallbacksAndMessages(null);
        handler = null;
    }
    private Handler handler = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            if(!isFinishing()){
                switch (msg.what){
                    case 0:
                        if(finishCount<selectBeans.size()){
                            datasToBitmap(selectBeans.get(finishCount));
                        }else {
                            //结束
                            loadListener.onComplete(new ArrayList<>(),finishCount);
                            if(failCount>0){
                                Toast.makeText(mContext, String.format(getString(R.string.addface_tip2),failCount,failStr.toString()), Toast.LENGTH_LONG).show();
                            }
                        }
                        break;
                }
            }
        }
    };
    private List<FaceUserBean> selectBeans = new ArrayList<>();
    private int finishCount = 0;
    private int failCount = 0;
    private StringBuilder failStr = new StringBuilder();
    private void datasToBitmap(FaceUserBean bean){
        // ä½¿ç”¨ Glide åŠ è½½å›¾ç‰‡å¹¶è½¬æ¢ä¸º Bitmap
        Glide.with(this)
                .asBitmap()
                .load(bean.getFaceImg())
                .addListener(new RequestListener<Bitmap>() {
                    @Override
                    public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource) {
                        //加载失败
                        Timber.d("====>图片下载失败%s",bean.getMemberName());
                        failCount++;
                        if(failStr.length()>0){
                            failStr.append(",");
                        }
                        failStr.append(bean.getMemberName());
                        finishCount++;
                        loadListener.onLoad(finishCount, mSelectCount, finishCount * 1.0f / mSelectCount);
                        if (finishCount == mSelectCount) {
                            loadListener.onComplete(new ArrayList<>(), finishCount);
                            if(failCount>0){
                                Toast.makeText(mContext, String.format(getString(R.string.addface_tip2),failCount,failStr.toString()), Toast.LENGTH_LONG).show();
                            }
                        }
                        handler.sendEmptyMessage(0);
                        return false;
                    }
                    @Override
                    public boolean onResourceReady(Bitmap bitmap, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource) {
                        boolean fail = true;
                        if (bitmap != null) {
                            byte[] secondFeature = new byte[512];
                            // æå–特征值
                            float ret = FaceSDKManager.getInstance().personDetect(bitmap, secondFeature,
                                    FaceUtils.getInstance().getBDFaceCheckConfig(), AddFaceActivity.this);
                            // æå–特征值
                            if (ret != -1) {
                                //有人脸
                                // åˆ¤æ–­è´¨é‡æ£€æµ‹ï¼Œé’ˆå¯¹æ¨¡ç³Šåº¦ã€é®æŒ¡ã€è§’度
                                if (ret == 128) {
                                    Timber.d("====>图片特征抽取成功: %s", bean.getMemberName());
                                    //插入数据库
                                    User user = FaceApi.getInstance().getByUserId(bean.getGroupId(), bean.getMemberId());
                                    boolean isSave = false;
                                    if (user == null) {
                                        //新增
                                        isSave = FaceApi.getInstance().registerUserIntoDBmanager(bean.getGroupId(),
                                                bean.getMemberId(), bean.getMemberName(), bean.getFaceImg(), JSON.toJSONString(bean), secondFeature);
                                    } else {
                                        //更新
                                        user.setUserName(bean.getMemberName());
                                        user.setImageName(bean.getFaceImg());
                                        user.setFeature(secondFeature);
                                        isSave = FaceApi.getInstance().userUpdateOnly(user);
                                    }
                                    if (isSave) {
                                        //保存成功
                                        Timber.d("====>录入成功%s",bean.getMemberName());
                                        fail = false;
                                    } else {
                                        Timber.d("====>录入失败%s",bean.getMemberName());
                                    }
                                } else {
                                    Timber.d("====>图片特征抽取失败%s",bean.getMemberName());
                                }
                            } else {
                                // ä¸Šä¼ å›¾ç‰‡æ— äººè„¸éšè—
                                Timber.d("====>图片特征抽取失败%s",bean.getMemberName());
                            }
                        }
                        if(fail){
                            failCount++;
                            if(failStr.length()>0){
                                failStr.append(",");
                            }
                            failStr.append(bean.getMemberName());
                        }else {
                            bean.setChecked(false);
                        }
                        finishCount++;
                        loadListener.onLoad(finishCount, mSelectCount, finishCount * 1.0f / mSelectCount);
                        if (finishCount == mSelectCount) {
                            loadListener.onComplete(new ArrayList<>(), finishCount);
                            if(failCount>0){
                                Toast.makeText(mContext, String.format(getString(R.string.addface_tip2),failCount,failStr.toString()), Toast.LENGTH_LONG).show();
                            }
                        }
                        handler.sendEmptyMessage(0);
                        return false;
                    }
                })
                .into(new SimpleTarget<Bitmap>() {
                    @Override
                    public void onResourceReady(@NonNull Bitmap bitmap, @Nullable Transition<? super Bitmap> transition) {
                    }
                });
                /*FrescoUtils.loadImage(this, bean.getFaceUrl(), 0, 0, new IResult<Bitmap>() {
                    @Override
                    public void onResult(Bitmap bitmap) {
                        if(handler.hasMessages(0)){
                            handler.removeMessages(0);
                        }
                        boolean fail = true;
                        if (bitmap != null) {
                            byte[] secondFeature = new byte[512];
                            // æå–特征值
                            float ret = FaceSDKManager.getInstance().personDetect(bitmap, secondFeature,
                                    FaceUtils.getInstance().getBDFaceCheckConfig(), AddFaceActivity.this);
                            if (bitmap != null && !bitmap.isRecycled()) {
                                //销毁图片
                                bitmap.recycle();
                            }
                            // æå–特征值
                            if (ret != -1) {
                                //有人脸
                                // åˆ¤æ–­è´¨é‡æ£€æµ‹ï¼Œé’ˆå¯¹æ¨¡ç³Šåº¦ã€é®æŒ¡ã€è§’度
                                if (ret == 128) {
                                    Timber.d("====>图片特征抽取成功: %s", bean.getMemberName());
                                    //插入数据库
                                    User user = FaceApi.getInstance().getByUserId(bean.getType(), bean.getId());
                                    boolean isSave = false;
                                    if (user == null) {
                                        //新增
                                        isSave = FaceApi.getInstance().registerUserIntoDBmanager(bean.getType(),
                                                bean.getId(), bean.getMemberName(), bean.getFaceUrl(), JSON.toJSONString(bean), secondFeature);
                                    } else {
                                        //更新
                                        user.setUserName(bean.getMemberName());
                                        user.setImageName(bean.getFaceUrl());
                                        user.setFeature(secondFeature);
                                        isSave = FaceApi.getInstance().userUpdateOnly(user);
                                    }
                                    if (isSave) {
                                        //保存成功
                                        Timber.d("====>录入成功%s",bean.getMemberName());
                                        fail = false;
                                    } else {
                                        Timber.d("====>录入失败%s",bean.getMemberName());
                                    }
                                } else {
                                    Timber.d("====>图片特征抽取失败%s",bean.getMemberName());
                                }
                            } else {
                                // ä¸Šä¼ å›¾ç‰‡æ— äººè„¸éšè—
                                Timber.d("====>图片特征抽取失败%s",bean.getMemberName());
                            }
                        } else {
                            Timber.d("====>图片下载失败%s",bean.getMemberName());
                        }
                        bean.setChecked(false);
                        if(fail){
                            failCount++;
                            if(failStr.length()>0){
                                failStr.append(",");
                            }
                            failStr.append(bean.getMemberName());
                        }
                        finishCount++;
                        loadListener.onLoad(finishCount, mSelectCount, finishCount * 1.0f / mSelectCount);
                        if (finishCount == mSelectCount) {
                            loadListener.onComplete(new ArrayList<>(), finishCount);
                            if(failCount>0){
                                Toast.makeText(mContext, "共"+failCount+"条导入失败【"+failStr.toString()+"】", Toast.LENGTH_LONG).show();
                            }
                        }
                    }
                });*/
    }
    private void initView() {
        mRecyclerUserManager = findViewById(R.id.recycler_user_manager);
        mRecyclerUserManager.setOnClickListener(this);
        RecyclerView.LayoutManager layoutManager = new GridLayoutManager(mContext,2);
        mRecyclerUserManager.setLayoutManager(layoutManager);
        // title相关的控件
        mRelativeStandard = findViewById(R.id.relative_standard);
        mLinearSearch = findViewById(R.id.linear_title_search);
        mImageIconSearch = findViewById(R.id.image_icon_research);
        mImageIconSearch.setOnClickListener(this);
        mTextCancel = findViewById(R.id.text_cancel);
        mTextCancel.setOnClickListener(this);
        mRelativeEmpty = findViewById(R.id.relative_empty);
        mTextEmpty = findViewById(R.id.text_empty);
        // åˆ é™¤ç›¸å…³çš„æŽ§ä»¶
        mRelativeDelete = findViewById(R.id.relative_botton_delete);
        mRelativeDelete.setOnClickListener(this);
        mCheckAll = findViewById(R.id.check_all);
        mCheckAll.setOnCheckedChangeListener(this);
        textAll = findViewById(R.id.text_all);
        textAll.setOnClickListener(this);
        mTextDelete = findViewById(R.id.text_delete);
        mTextDelete.setOnClickListener(this);
        // title中的搜索框取消按钮
        Button btnTitleCancel = findViewById(R.id.btn_title_cancel);
        btnTitleCancel.setOnClickListener(this);
        ImageView imageBack = findViewById(R.id.image_back);
        imageBack.setOnClickListener(this);
        ImageView imageInputDelete = findViewById(R.id.image_input_delete);
        imageInputDelete.setOnClickListener(this);
        mTipDialog = new TipDialog(mContext);
        mTipDialog.setOnTipDialogClickListener(this);
        mFaceUserAdapter = new FaceRcvAdapter(this, R.layout.face_rcv_item, new FaceRcvAdapter.OnItemClick() {
            @Override
            public void onItemClick(FaceUserBean item) {
                // å¦‚果当前item未选中,则选中
                if (item.isChecked()) {
                    mSelectCount++;
                    mTextDelete.setText(getString(R.string.addface_drrl)+"(" + mSelectCount + ")");
                    mTextDelete.setTextColor(Color.parseColor("#F34B56"));
                } else {
                    // å¦‚果当前item已经选中,则取消选中
                    mSelectCount--;
                    mTextDelete.setText(getString(R.string.addface_drrl)+"(" + mSelectCount + ")");
                    if (mSelectCount == 0) {
                        mTextDelete.setTextColor(Color.parseColor("#666666"));
                    }
                }
            }
        });
        mRecyclerUserManager.setAdapter(mFaceUserAdapter);
        progressBar = findViewById(R.id.progress_bar);
        progressText = findViewById(R.id.progress_text);
        progressGroup = findViewById(R.id.progress_group);
        // title中的搜索框
        mEditTitleSearch = findViewById(R.id.edit_title_search);
        // æœç´¢æ¡†è¾“入监听事件
        mEditTitleSearch.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (mUserInfoList!=null&&s != null) {
                    // è¯»å–数据库,获取用户信息
                    if(s.toString().trim().length()==0){
                        mFaceUserAdapter.refreshData(mUserInfoList);
                    }else {
                        List<FaceUserBean> beans = new ArrayList<>();
                        for(FaceUserBean d:mUserInfoList){
                            if(s.toString().trim().contains(d.getMemberName())){
                                beans.add(d);
                            }
                        }
                        mFaceUserAdapter.refreshData(beans);
                    }
                }
            }
            @Override
            public void afterTextChanged(Editable s) {
            }
        });
    }
    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.btn_title_cancel) {  // å–消按钮
            mEditTitleSearch.setText("");
            mLinearSearch.setVisibility(View.GONE);
            mRelativeStandard.setVisibility(View.VISIBLE);
        } else if (id == R.id.image_icon_research) {  // æœç´¢æŒ‰é’®
            mLinearSearch.setVisibility(View.VISIBLE);
            mRelativeStandard.setVisibility(View.GONE);
        } else if (id == R.id.image_back) {
            finish();
        } else if (id == R.id.text_all) {
            mCheckAll.setChecked(!mCheckAll.isChecked());
        }else if (id == R.id.relative_delete) {       // æ˜¾ç¤ºå¯¼å…¥äººè„¸UI
            updateDeleteUI(true);
        } else if (id == R.id.text_cancel) {           // æ‰¹é‡å¯¼å…¥äººè„¸å–消
            updateDeleteUI(false);
        } else if (id == R.id.text_delete) {           // æ‰¹é‡å¯¼å…¥äººè„¸
            if (mSelectCount == 0) {
                Toast.makeText(mContext, getString(R.string.addface_tip3), Toast.LENGTH_SHORT).show();
                return;
            }
            if(FaceSDKManager.initStatus != FaceSDKManager.SDK_MODEL_LOAD_SUCCESS){
                Toast.makeText(mContext, getString(R.string.addface_tip4), Toast.LENGTH_SHORT).show();
                return;
            }
            mTipDialog.show();
            mTipDialog.setTextTitle(getString(R.string.addface_qrdr));
            mTipDialog.setTextMessage(getString(R.string.addface_tip5));
            mTipDialog.setTextConfirm(getString(R.string.addface_drrl)+"(" + mSelectCount + ")");
            mTipDialog.setCancelable(false);
        } else if (id == R.id.image_input_delete) {
            mEditTitleSearch.setText("");
        } else if (id == R.id.recycler_user_manager) {
            KeyboardsUtils.hintKeyBoards(v);
        } else if (id == R.id.relative_botton_delete) {
            Timber.d( "relative_botton_delete");
        }
    }
    /**
     * å…¨é€‰å¤šé€‰æ¡†çš„监听事件
     */
    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        if (isChecked) {      // å…¨é€‰
            mSelectCount = mUserInfoList.size();
            for (int i = 0; i < mUserInfoList.size(); i++) {
                mUserInfoList.get(i).setChecked(true);
            }
            mTextDelete.setTextColor(Color.parseColor("#F34B56"));
        } else {             // å–消全选
            mSelectCount = 0;
            for (int i = 0; i < mUserInfoList.size(); i++) {
                mUserInfoList.get(i).setChecked(false);
            }
            mTextDelete.setTextColor(Color.parseColor("#666666"));
        }
        mTextDelete.setText(getString(R.string.addface_drrl)+"(" + mSelectCount + ")");
        mFaceUserAdapter.notifyDataSetChanged();
    }
    // å¯¹è¯æ¡†â€œå–消”按钮
    @Override
    public void onCancel() {
        if (mIsLongClick) {
            resetDeleteData();
            mIsLongClick = false;
        }
        mFaceUserAdapter.notifyDataSetChanged();
        if (mTipDialog != null) {
            mTipDialog.dismiss();
        }
    }
    private DBLoadListener loadListener = new DBLoadListener() {
        @Override
        public void onStart(final int successCount) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    progressGroup.setVisibility(View.VISIBLE);
                    progressBar.setProgress(0);
                    progressText.setText(0 + "/" + successCount);
                }
            });
        }
        @Override
        public void onLoad(final int finishCount, final int successCount, final float progress) {
//            if (successCount > 50 || successCount == 0) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Timber.d("====>人脸导入进度%s",finishCount+"=="+successCount+"=="+progress);
                    progressBar.setProgress((int) (progress * 100));
                    progressText.setText(finishCount + "/" + successCount);
                }
            });
//            }
        }
        @Override
        public void onComplete(List<User> features, final int successCount) {
            progressGroup.setVisibility(View.GONE);
            mFaceUserAdapter.notifyDataSetChanged();
            mCheckAll.setChecked(false);
        }
        @Override
        public void onFail(int finishCount, int successCount, List<User> features) {
        }
    };
    // å¯¹è¯æ¡†â€œå¯¼å…¥äººè„¸â€æŒ‰é’®
    @Override
    public void onConfirm(String tipType) {
        if (mTipDialog != null) {
            mTipDialog.dismiss();
        }
        if (mSelectCount != 0) {
            //导入人脸
            selectBeans.clear();
            for(FaceUserBean bean:mUserInfoList){
                if(bean.isChecked()) {
                    selectBeans.add(bean);
                }
            }
            loadListener.onStart(mSelectCount);
            finishCount = 0;
            failCount = 0;
            failStr = new StringBuilder();
            handler.sendEmptyMessage(0);
        } else {
            updateDeleteUI(false);
        }
    }
    // æ›´æ–°å¯¼å…¥äººè„¸ç›¸å…³çš„UI
    private void updateDeleteUI(boolean isShowDeleteUI) {
        mRelativeDelete.setVisibility(View.VISIBLE);
        mImageIconSearch.setVisibility(View.GONE);
        mTextCancel.setVisibility(View.VISIBLE);
        mFaceUserAdapter.notifyDataSetChanged();
    }
    private void resetDeleteData() {
        mSelectCount = 0;
        for (int i = 0; i < mUserInfoList.size(); i++) {
            mUserInfoList.get(i).setChecked(false);
        }
        mTextDelete.setText(getString(R.string.addface_drrl));
    }
    /**
     * ç‚¹å‡»éžç¼–辑区域收起键盘
     * èŽ·å–ç‚¹å‡»äº‹ä»¶
     */
    @CallSuper
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            View view = getCurrentFocus();
            if (KeyboardsUtils.isShouldHideKeyBord(view, ev)) {
                KeyboardsUtils.hintKeyBoards(view);
            }
        }
        return super.dispatchTouchEvent(ev);
    }
}