2016-01-04 60 views
2

我試圖做指紋演示。但是,發生以下異常。我得到NullPointerException我的按鈕點擊以下我在指紋演示中遇到了一些錯誤

01-04 11:35:18.647 3295-3295/? E/AndroidRuntime: FATAL EXCEPTION: main 
Process: com.letsnurture.fingerprint, PID: 3295 
java.lang.NullPointerException: Attempt to invoke virtual method 'void javax.crypto.Cipher.init(int, java.security.Key)' on a null object reference 
    at com.letsnurture.fingerprint.MainActivity.initCipher(MainActivity.java:179) 
    at com.letsnurture.fingerprint.MainActivity.access$000(MainActivity.java:45) 
    at com.letsnurture.fingerprint.MainActivity$1.onClick(MainActivity.java:131) 
    at android.view.View.performClick(View.java:5198) 
    at android.view.View$PerformClick.run(View.java:21147) 
    at android.os.Handler.handleCallback(Handler.java:739) 
    at android.os.Handler.dispatchMessage(Handler.java:95) 
    at android.os.Looper.loop(Looper.java:148) 
    at android.app.ActivityThread.main(ActivityThread.java:5417) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

    01-04 12:08:55.382 1836-2383/? E/MDM: [83] b.run: Couldn't connect to Google API client: ConnectionResult{statusCode=API_UNAVAILABLE, resolution=null, message=null} 

我的代碼:

import android.Manifest; 
import android.content.pm.PackageManager; 
import android.os.Bundle; 
import android.support.v4.app.ActivityCompat; 
import android.support.v7.app.AppCompatActivity; 
import android.support.v7.widget.Toolbar; 
import android.view.View; 
import android.view.Menu; 
import android.view.MenuItem; 
import android.app.KeyguardManager; 
import android.content.Intent; 
import android.content.SharedPreferences; 
import android.hardware.fingerprint.FingerprintManager; 
import android.security.keystore.KeyGenParameterSpec; 
import android.security.keystore.KeyPermanentlyInvalidatedException; 
import android.security.keystore.KeyProperties; 
import android.util.Base64; 
import android.util.Log; 
import android.widget.Button; 
import android.widget.TextView; 
import android.widget.Toast; 


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 javax.crypto.BadPaddingException; 
import javax.crypto.Cipher; 
import javax.crypto.IllegalBlockSizeException; 
import javax.crypto.KeyGenerator; 
import javax.crypto.NoSuchPaddingException; 
import javax.crypto.SecretKey; 
import javax.inject.Inject; 


public class MainActivity extends AppCompatActivity { 


    private static final String TAG = MainActivity.class.getSimpleName(); 

    private static final String DIALOG_FRAGMENT_TAG = "myFragment"; 
    private static final String SECRET_MESSAGE = "Very secret message"; 
    /** Alias for our key in the Android Key Store */ 
    private static final String KEY_NAME = "my_key"; 

    @Inject 
    KeyguardManager mKeyguardManager; 
    @Inject 
    FingerprintManager mFingerprintManager; 
    @Inject 
    FingerprintAuthenticationDialogFragment mFragment; 
    @Inject 
    KeyStore mKeyStore; 
    @Inject 
    KeyGenerator mKeyGenerator; 
    @Inject 
    Cipher mCipher; 
    @Inject 
    SharedPreferences mSharedPreferences; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
     setSupportActionBar(toolbar); 


     Button purchaseButton = (Button) findViewById(R.id.purchase_button); 
     mKeyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE); 
     if (!mKeyguardManager.isKeyguardSecure()) { 
      // Show a message that the user hasn't set up a fingerprint or lock screen. 
      Toast.makeText(this, 
        "Secure lock screen hasn't set up.\n" 
          + "Go to 'Settings -> Security -> Fingerprint' to set up a fingerprint", 
        Toast.LENGTH_LONG).show(); 
      purchaseButton.setEnabled(false); 
      return; 
     } 

     //noinspection ResourceType 
     mFingerprintManager = (FingerprintManager) getSystemService(FINGERPRINT_SERVICE); 
     if (ActivityCompat.checkSelfPermission(this, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) { 
      // TODO: Consider calling 
      // ActivityCompat#requestPermissions 
      // here to request the missing permissions, and then overriding 
      // public void onRequestPermissionsResult(int requestCode, String[] permissions, 
      //           int[] grantResults) 
      // to handle the case where the user grants the permission. See the documentation 
      // for ActivityCompat#requestPermissions for more details. 
      return; 
     } 
     if (!mFingerprintManager.hasEnrolledFingerprints()) { 
      purchaseButton.setEnabled(false); 
      // This happens when no fingerprints are registered. 
      Toast.makeText(this, 
        "Go to 'Settings -> Security -> Fingerprint' and register at least one fingerprint", 
        Toast.LENGTH_LONG).show(); 
      return; 
     } 
     try { 
      try { 
       createKey(); 
      } catch (NoSuchProviderException e) { 
       e.printStackTrace(); 
      } 
     } catch (KeyStoreException e) { 
      e.printStackTrace(); 
     } 
     purchaseButton.setEnabled(true); 
     purchaseButton.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       findViewById(R.id.confirmation_message).setVisibility(View.GONE); 
       findViewById(R.id.encrypted_message).setVisibility(View.GONE); 



       // Set up the crypto object for later. The object will be authenticated by use 
       // of the fingerprint. 
       try { 
        if (initCipher()) { 

         // Show the fingerprint dialog. The user has the option to use the fingerprint with 
         // crypto, or you can fall back to using a server-side verified password. 
         mFragment.setCryptoObject(new FingerprintManager.CryptoObject(mCipher)); 
         boolean useFingerprintPreference = mSharedPreferences 
           .getBoolean(getString(R.string.use_fingerprint_to_authenticate_key), 
             true); 
         if (useFingerprintPreference) { 
          mFragment.setStage(
            FingerprintAuthenticationDialogFragment.Stage.FINGERPRINT); 
         } else { 
          mFragment.setStage(
            FingerprintAuthenticationDialogFragment.Stage.PASSWORD); 
         } 
         mFragment.show(getFragmentManager(), DIALOG_FRAGMENT_TAG); 
        } else { 
         // This happens if the lock screen has been disabled or or a fingerprint got 
         // enrolled. Thus show the dialog to authenticate with their password first 
         // and ask the user if they want to authenticate with fingerprints in the 
         // future 
         mFragment.setCryptoObject(new FingerprintManager.CryptoObject(mCipher)); 
         mFragment.setStage(
           FingerprintAuthenticationDialogFragment.Stage.NEW_FINGERPRINT_ENROLLED); 
         mFragment.show(getFragmentManager(), DIALOG_FRAGMENT_TAG); 
        } 
       } catch (NoSuchPaddingException e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 

    } 

    /** 
    * Initialize the {@link Cipher} instance with the created key in the {@link #createKey()} 
    * method. 
    * 
    * @return {@code true} if initialization is successful, {@code false} if the lock screen has 
    * been disabled or reset after the key was generated, or if a fingerprint got enrolled after 
    * the key was generated. 
    */ 

    private boolean initCipher() throws NoSuchPaddingException { 
     try { 
      mKeyStore.load(null); 
      SecretKey key = (SecretKey) mKeyStore.getKey(KEY_NAME, null); 
      // mCipher = Cipher.getInstance("DES/CBC"); 
      mCipher.init(Cipher.ENCRYPT_MODE, key); 
      return true; 
     } catch (KeyPermanentlyInvalidatedException e) { 
      return false; 
     } catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException 
       | NoSuchAlgorithmException | InvalidKeyException e) { 
      throw new RuntimeException("Failed to init Cipher", e); 
     } 
    } 

    public void onPurchased(boolean withFingerprint) { 
     if (withFingerprint) { 
      // If the user has authenticated with fingerprint, verify that using cryptography and 
      // then show the confirmation message. 
      tryEncrypt(); 
     } else { 
      // Authentication happened with backup password. Just show the confirmation message. 
      showConfirmation(null); 
     } 
    } 

    // Show confirmation, if fingerprint was used show crypto information. 
    private void showConfirmation(byte[] encrypted) { 
     findViewById(R.id.confirmation_message).setVisibility(View.VISIBLE); 
     if (encrypted != null) { 
      TextView v = (TextView) findViewById(R.id.encrypted_message); 
      v.setVisibility(View.VISIBLE); 
      v.setText(Base64.encodeToString(encrypted, 0 /* flags */)); 
     } 
    } 

    /** 
    * Tries to encrypt some data with the generated key in {@link #createKey} which is 
    * only works if the user has just authenticated via fingerprint. 
    */ 
    private void tryEncrypt() { 
     try { 
      byte[] encrypted = mCipher.doFinal(SECRET_MESSAGE.getBytes()); 
      showConfirmation(encrypted); 
     } catch (BadPaddingException | IllegalBlockSizeException e) { 
      Toast.makeText(this, "Failed to encrypt the data with the generated key. " 
        + "Retry the purchase", Toast.LENGTH_LONG).show(); 
      Log.e(TAG, "Failed to encrypt the data with the generated key." + e.getMessage()); 
     } 
    } 

    /** 
    * Creates a symmetric key in the Android Key Store which can only be used after the user has 
    * authenticated with fingerprint. 
    */ 
    public void createKey() throws KeyStoreException, NoSuchProviderException { 
     // The enrolling flow for fingerprint. This is where you ask the user to set up fingerprint 
     // for your flow. Use of keys is necessary if you need to know if the set of 
     // enrolled fingerprints has changed. 

     // mKeyStore=(KeyStore)getSystemService(Context); 
     mKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); 

     try { 

      mKeyStore.load(null); 
      // Set the alias of the entry in Android KeyStore where the key will appear 
      // and the constrains (purposes) in the constructor of the Builder 
      mKeyGenerator = mKeyGenerator.getInstance("AES", "BC"); 
      mKeyGenerator.init(new KeyGenParameterSpec.Builder(KEY_NAME, 
        KeyProperties.PURPOSE_ENCRYPT | 
          KeyProperties.PURPOSE_DECRYPT) 
        .setBlockModes(KeyProperties.BLOCK_MODE_CBC) 
        // Require the user to authenticate with a fingerprint to authorize every use 
        // of the key 
        .setUserAuthenticationRequired(true) 
        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) 
        .build()); 
      mKeyGenerator.generateKey(); 
     } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException 
       | CertificateException | IOException e) { 

     } 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     getMenuInflater().inflate(R.menu.menu_main, menu); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     int id = item.getItemId(); 

     if (id == R.id.action_settings) { 
      Intent intent = new Intent(this, SettingsActivity.class); 
      startActivity(intent); 
      return true; 
     } 
     return super.onOptionsItemSelected(item); 
    } 
}                               
+0

你試過調試你的代碼嗎? –

+0

你有解決方案 – user1767260

回答

0

我嘗試過同樣的演示,它爲我工作。

我想你應該考慮這些注入註釋是否適合你。如果它們不起作用,則必須通過使用「new」後跟構造函數來自己初始化這些實例。否則,你會得到那個空對象引用錯誤。

相關問題