以下は、指紋で認証するために使用できる2つのクラスです。彼らはパーミッションの取り扱いや輸入のような小さな問題になります。これは指紋認証の作業コードです。 FingerPrintHandlerクラス
import android.accounts.Account;
import android.accounts.AccountManager;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
import android.Manifest;
import android.os.Build;
import android.os.CancellationSignal;
import android.support.v4.app.ActivityCompat;
import yasiriqbal.ethereum.R;
import yasiriqbal.ethereum.util.SessionManager;
@TargetApi(Build.VERSION_CODES.M)
public class FingerprintHandler extends FingerprintManager.AuthenticationCallback {
// You should use the CancellationSignal method whenever your app can no longer process user input, for example when your app goes
// into the background. If you don’t use this method, then other apps will be unable to access the touch sensor, including the lockscreen!//
private CancellationSignal cancellationSignal;
private Context context;
public FingerprintHandler(Context mContext) {
context = mContext;
}
//Implement the startAuth method, which is responsible for starting the fingerprint authentication process//
public void startAuth(FingerprintManager manager, FingerprintManager.CryptoObject cryptoObject) {
cancellationSignal = new CancellationSignal();
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
return;
}
manager.authenticate(cryptoObject, cancellationSignal, 0, this, null);
}
public void StopListener() {
try {
if (cancellationSignal != null)
cancellationSignal.cancel();
cancellationSignal = null;
}catch (Exception e)
{}
}
@Override
//onAuthenticationError is called when a fatal error has occurred. It provides the error code and error message as its parameters//
public void onAuthenticationError(int errMsgId, CharSequence errString) {
//I’m going to display the results of fingerprint authentication as a series of toasts.
//Here, I’m creating the message that’ll be displayed if an error occurs//
}
@Override
//onAuthenticationFailed is called when the fingerprint doesn’t match with any of the fingerprints registered on the device//
public void onAuthenticationFailed() {
}
@Override
//onAuthenticationHelp is called when a non-fatal error has occurred. This method provides additional information about the error,
//so to provide the user with as much feedback as possible I’m incorporating this information into my toast//
public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
}
@Override
//onAuthenticationSucceeded is called when a fingerprint has been successfully matched to one of the fingerprints stored on the user’s device//
public void onAuthenticationSucceeded(
FingerprintManager.AuthenticationResult result) {
if (new SessionManager(context).getUsername() != null && !new SessionManager(context).getUsername().isEmpty()) {
String userName = new SessionManager(context).getUsername();
String pass = new SessionManager(context).getPass();
if (pass != null) {
((SigninActivity) context).requestLoginToServer(userName, pass);
((SigninActivity) context).isSignInButtonClicked = false;
}
}
//context.startActivity(new Intent(context, DashboardActivity.class));
}
}
サインインもクラス
import android.Manifest;
import android.accounts.Account;
import android.accounts.AccountAuthenticatorActivity;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.annotation.TargetApi;
import android.app.KeyguardManager;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Typeface;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
import android.os.Handler;
import android.provider.ContactsContract;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TextInputEditText;
import android.support.design.widget.TextInputLayout;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v7.widget.AppCompatTextView;
import android.text.Editable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextWatcher;
import android.text.method.PasswordTransformationMethod;
import android.text.style.ForegroundColorSpan;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.gson.Gson;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import yasiriqbal.ethereum.EthereumApplication;
import yasiriqbal.ethereum.PermissionActivity;
import yasiriqbal.ethereum.R;
import yasiriqbal.ethereum.dashboad.DashboardActivity;
import yasiriqbal.ethereum.models.EthUserModel;
import yasiriqbal.ethereum.models.ServerMessage;
import yasiriqbal.ethereum.network.VolleyRequestHelper;
import yasiriqbal.ethereum.settings.ChangePasswordActivity;
import yasiriqbal.ethereum.signup.MobileCodeVerifyActivity;
import yasiriqbal.ethereum.signup.MobileNumberActivity;
import yasiriqbal.ethereum.signup.SignUpActivity;
import yasiriqbal.ethereum.util.Constants;
import yasiriqbal.ethereum.util.DialogErrorFragment;
import yasiriqbal.ethereum.util.DialogHelper;
import yasiriqbal.ethereum.util.Fonts;
import yasiriqbal.ethereum.util.MyUtils;
import yasiriqbal.ethereum.util.PermissionHandler;
import yasiriqbal.ethereum.util.SessionManager;
public class SigninActivity extends AccountAuthenticatorActivity implements View.OnClickListener, Response.Listener<JSONObject>, Response.ErrorListener {
public static final String PARAM_USER_PASS = "userpassword";
private static final int CODE_EMAIL_NOT_VERIFIED = 408;
private AppCompatTextView txt_loginscreen_not_register_member, txt_loginscreen_header,
txt_loginscreen_forgetpassword, txt_loginscreen_touchid;
private TextInputEditText edit_loginscreen_username, edit_loginscreen_password;
Button btn_loginscreen_signin;
PermissionHandler permissionHandler;
private TextInputLayout layout_loginscreen_password, layout_loginscreen_username;
private KeyStore keyStore;
private Cipher cipher;
private final int CODE_WRONG_PASSWORD = 401;
private final int CODE_INVALID_USER = 400;
private final int CODE_LOGIN_SUCCESS = 200;
public final int CODE_PROFILE_STATUS_COMPLETE = 2;
public final int CODE_MOBILE_NOT_VERIFY = 1;
private DialogHelper dialogHelper;
private final int ACCOUNT_PERMISSION_ID = 1234;
boolean isFromSetting = false;
private static final String KEY_NAME = "ethereum";
private Typeface qanelasRegularTypeFace;
private Typeface qanelasSemiBoldTypeFace;
private String previousUserName = "";
FingerprintHandler handler;
FingerprintManager mFingerprintManager;
public boolean isSignInButtonClicked = false;
FingerprintManager.CryptoObject cryptoObject;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sign_in);
if (permissionHandler.isMarshMallow()) {
authenticateWithFingerPrint();
if (permissionHandler.isPermissionAvailable(Manifest.permission.USE_FINGERPRINT)) {
setFingerprintConfig();
} else {
permissionHandler.requestPermission(Manifest.permission.USE_FINGERPRINT);
}
}//end of if is marshmallow
//dialogErrorFragment.show(getFragmentManager(),"dialog");
}//end of onCreate
@TargetApi(Build.VERSION_CODES.M)
private void authenticateWithFingerPrint() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
return;
}
mFingerprintManager = (FingerprintManager) getSystemService(Context.FINGERPRINT_SERVICE);
if (mFingerprintManager.isHardwareDetected()) {
KeyguardManager mKeyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
if (mKeyguardManager.isKeyguardSecure()) {
generateKey();
if (initCipher()) {
cryptoObject = new FingerprintManager.CryptoObject(cipher);
handler = new FingerprintHandler(this);
handler.startAuth(mFingerprintManager, cryptoObject);
}
} else {
Toast.makeText(this, "Lock Screen Security not enabled in Settings.", Toast.LENGTH_LONG).show();
}
}
}
@TargetApi(Build.VERSION_CODES.M)
protected void generateKey() {
try {
keyStore = KeyStore.getInstance("AndroidKeyStore");
} catch (Exception e) {
e.printStackTrace();
}
KeyGenerator keyGenerator;
try {
keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
throw new RuntimeException("Failed to get KeyGenerator instance", e);
}
try {
keyStore.load(null);
keyGenerator.init(new
KeyGenParameterSpec.Builder(KEY_NAME,
KeyProperties.PURPOSE_ENCRYPT |
KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setUserAuthenticationRequired(true)
.setEncryptionPaddings(
KeyProperties.ENCRYPTION_PADDING_PKCS7)
.build());
keyGenerator.generateKey();
} catch (NoSuchAlgorithmException |
InvalidAlgorithmParameterException
| CertificateException | IOException e) {
throw new RuntimeException(e);
}
}
//Create a new method that we’ll use to initialize our cipher//
@TargetApi(Build.VERSION_CODES.M)
public boolean initCipher() {
try {
//Obtain a cipher instance and configure it with the properties required for fingerprint authentication//
cipher = Cipher.getInstance(
KeyProperties.KEY_ALGORITHM_AES + "/"
+ KeyProperties.BLOCK_MODE_CBC + "/"
+ KeyProperties.ENCRYPTION_PADDING_PKCS7);
} catch (NoSuchAlgorithmException |
NoSuchPaddingException e) {
throw new RuntimeException("Failed to get Cipher", e);
}
try {
keyStore.load(null);
SecretKey key = (SecretKey) keyStore.getKey(KEY_NAME,
null);
cipher.init(Cipher.ENCRYPT_MODE, key);
//Return true if the cipher has been initialized successfully//
return true;
} catch (KeyPermanentlyInvalidatedException e) {
//Return false if cipher initialization failed//
return false;
} catch (KeyStoreException | CertificateException
| UnrecoverableKeyException | IOException
| NoSuchAlgorithmException | InvalidKeyException e) {
throw new RuntimeException("Failed to init Cipher", e);
}
}
//xml initalization
private void initResources() {
//textViews initalize
}//end of initResources
@Override
protected void onResume() {
super.onResume();
}//end of onResume
//here to discover fingerprint hardware and set views
@TargetApi(Build.VERSION_CODES.M)
@SuppressWarnings("MissingPermission")
private void setFingerprintConfig() {
FingerprintManager mFingerprintManager = (FingerprintManager) getSystemService(Context.FINGERPRINT_SERVICE);
if (mFingerprintManager.isHardwareDetected()) {
if (getPreviousUsername() != null && !getPreviousUsername().isEmpty() && mFingerprintManager.hasEnrolledFingerprints()) {
//TODO show finger print icon that this device support
} else {
//here means user is not enrolled for fingerpring
//TODO handle case when fingerprint not supported
}
}
}//end of setFingerprint
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (permissionHandler.PERMISSIONS_REQUEST == requestCode && grantResults.length > 0 && grantResults[0] > -1) {
setFingerprintConfig();
}
}
//onclick reciver for signin activity
@Override
public void onClick(View v) {
switch (v.getId()) {
default:
throw new IllegalArgumentException(v.getId() + " is not handle in onclick of signing activity");
}//end f switch
}//end of onClick
@Override
protected void onPause() {
super.onPause();
}
//here check if user profile complete then redirect to dashboard or then mobile verify
private void redirectUserAfterSuccessLogin(String data) throws JSONException {
if (!data.isEmpty()) {
Gson gsonForUser = new Gson();
new SessionManager(this).adToken(new JSONObject(data).getString("authenticationToken"));
EthUserModel ethUserModel = gsonForUser.fromJson(data, EthUserModel.class);
EthereumApplication.getInstance().setEthUserLoginObj(ethUserModel);
insertEthUserToContentProvider(ethUserModel);
if (!previousUserName.equals(ethUserModel.getEthUserName()) && !removeAccountFromAccountManager(ethUserModel, edit_loginscreen_password.getText().toString())) {
addAccountToAuthenticator(ethUserModel, edit_loginscreen_password.getText().toString());
startOtherActivity(ethUserModel);
//startSyncAdapter();
}//end of if for removeAccount return false
else {
startOtherActivity(ethUserModel);
//startSyncAdapter();
}//end of else
} else {
//here to show retry login
}
}//end of function
private void startOtherActivity(EthUserModel ethUserModel) {
if (isSignInButtonClicked)
new SessionManager(this).addData(edit_loginscreen_username.getText().toString(), edit_loginscreen_password.getText().toString());
if (txt_loginscreen_touchid.getVisibility() == View.VISIBLE)
try {
handler.StopListener();
} catch (Exception e) {
}
if (ethUserModel.getProfileStatus() == CODE_MOBILE_NOT_VERIFY) {
//redirect to mobile screen
startActivity(new Intent(this, MobileNumberActivity.class));
} else {
//redirect to dashboard if user not from setting
if (!getIntent().getBooleanExtra(Constants.ARG_IS_USER_FROM_SETTING, false)) {
if (EthereumApplication.getInstance().getEthUserLoginObj().getEthUserDoubleAuthenticationStatus() == Constants.ResultCode.CODE_DOUBLE_AUTHENTICATION_TRUE)
startActivity(new Intent(this, MobileCodeVerifyActivity.class)
.putExtra(Constants.MobileCodeVerifyActivity.IS_FROM_SIGNIN, true)
.putExtra(Constants.MobileNumberActivity.EXTRA_MOBILE_NUMBER, EthereumApplication.getInstance().getEthUserLoginObj().getMobileNum()));
else
startActivity(new Intent(this, DashboardActivity.class));
finish();
}
}//end of else
}//end of function
@Override
protected void onStop() {
super.onStop();
}
}//end of activity