2014-02-24 42 views
3

感謝您花時間閱讀本文。我正在處理涉及Android的項目中遇到了一個非常奇怪的「NoSuchMethodError」。我無法弄清楚這一點,因爲它無視我所有的邏輯。NoSuchMethodError對我的Android設備運行時確實存在的方法

package com.project.qrcode 

import android.security.KeyStore; 
import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.io.UnsupportedEncodingException; 
import java.security.MessageDigest; 
import java.security.NoSuchAlgorithmException; 

import jim.h.common.android.lib.zxing.config.ZXingLibConfig; 
import jim.h.common.android.lib.zxing.integrator.IntentIntegrator; 
import jim.h.common.android.lib.zxing.integrator.IntentResult; 
import android.app.Activity; 
import android.content.ActivityNotFoundException; 
import android.content.Intent; 
import android.os.Build; 
import android.os.Bundle; 
import android.os.Handler; 
import android.util.Log; 
import android.view.Menu; 
import android.view.View; 
import android.widget.Button; 
import android.widget.TextView; 
import android.widget.Toast; 

public class MainActivity extends Activity { 

    private ZXingLibConfig zxingLibConfig; 
    private Handler handler = new Handler(); 
    private TextView txtScanResult; 
    KeyStore ks = KeyStore.getInstance(); 
    SecretKeyStore secretKeyStore = new SecretKeyStore(); 
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 

    byte[] hashedBytes; 
    String decoded; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     try { 
       if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { 
       startActivity(new Intent("android.credentials.UNLOCK")); 
       } else { 
       startActivity(new Intent("com.android.credentials.UNLOCK")); 
       } 
      } catch (ActivityNotFoundException e) { 
       Log.e(getPackageName(), "No UNLOCK activity: " + e.getMessage(), e); 
     } 

     zxingLibConfig = new ZXingLibConfig(); 
     zxingLibConfig.useFrontLight = true; 
     txtScanResult = (TextView) findViewById(R.id.scan_result); 

     Button scanButton = (Button) findViewById(R.id.scan_button); 

     //Set a listener on the scan button 
     scanButton.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       if (!checkIfKeyStored()) { 
        Toast keyerror = Toast.makeText(getBaseContext(), "You need to complete setup first", Toast.LENGTH_SHORT); 
        keyerror.show(); 
        return; 
       } 
       IntentIntegrator.initiateScan(MainActivity.this, zxingLibConfig); 
      } 
     }); 
     Log.v(getPackageName(), "Listener set on scan button"); 

     Button setupButton = (Button) findViewById(R.id.setup_button); 

     // Set a listener on the setup button 
     setupButton.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       if (checkIfKeyStored()) { 
        Log.v(getPackageName(), "Key is already stored"); 
        Toast keyerror = Toast.makeText(getBaseContext(), "You have already completed setup", Toast.LENGTH_SHORT); 
        keyerror.show(); 
        return; 
       } 
       Log.v(getPackageName(), "Key not stored, proceeding with setup"); 
       IntentIntegrator.initiateScan(MainActivity.this, zxingLibConfig); 
      } 
     }); 
     Log.v(getPackageName(), "Listener set on setup button"); 
    } 

    protected boolean checkIfKeyStored() { 
     String[] keyNames = ks.saw(""); 

     if(keyNames.length == 0) { 
      return false; 
     } 

     return true; 
    } 

    // IF setup is done i.e. key is stored send to server 
    // Otherwise store on phone 

    @Override 
    public void onActivityResult(int requestCode, int resultCode, Intent data) { 
     super.onActivityResult(requestCode, resultCode, data); 

     Log.v(getPackageName(), "Scanned QRCode"); 

     if (requestCode == IntentIntegrator.REQUEST_CODE) { 
      IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data); 

      if (scanResult == null) { 
       Log.v(getPackageName(), "Scanned nothing"); 
       return; 
      } 

      //Contents of the QRCode 
      Log.v(getPackageName(), "Scan complete, getting result"); 
      final String result = scanResult.getContents(); 
      Log.v(getPackageName(), "Scanned the following code "+ result); 

      //If there is already a secret key stored i.e. setup already done 
      if (checkIfKeyStored()) { 
       Log.v(getPackageName(), "Key already stored, encrypting"); 
       try { 
        MessageDigest digest = MessageDigest.getInstance("SHA1PRNG"); 
        Log.v(getPackageName(), "Got SHA1PRNG instance"); 

        byte[] keyBytes = ks.get("twofactorkey"); 
        byte[] resultBytes = result.getBytes("UTF-8"); 

        Log.v(getPackageName(), "Got Bytes"); 

        outputStream.write(resultBytes); 
        outputStream.write(keyBytes); 
        Log.v(getPackageName(), "Wrote Bytes to output stream"); 

        byte[] bytesToEncrypt = outputStream.toByteArray(); 
        Log.v(getPackageName(), "Wrote to Byte array"); 

        hashedBytes = digest.digest(bytesToEncrypt); 
        decoded = new String(hashedBytes, "UTF-8"); 
        Log.v(getPackageName(), "Coverted bytes to String"); 
       } catch (NoSuchAlgorithmException e) { 
        e.printStackTrace(); 
       } catch (UnsupportedEncodingException e) { 
        e.printStackTrace(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 

       handler.post(new Runnable() { 
        @Override 
        public void run() { 
         txtScanResult.setText(decoded); 
         Log.v(getPackageName(), "Set TextView"); 
        } 
       }); 
      } 
      else //This is the first time scanning a QRCode, i.e. Setup 
      { 
       Log.v(getPackageName(), "Key not stored, first time setup"); 

       byte[] resultBytes; 

       try { 
        resultBytes = result.getBytes("UTF-8"); 
        Log.v(getPackageName(), "Result byte array: " + resultBytes); 

        boolean success = ks.put("twofactorkey", resultBytes); 

        if (!success) { 
          int errorCode = ks.getLastError(); 
          throw new RuntimeException("Keystore error: " + errorCode); 
        } 

       } catch (UnsupportedEncodingException e) { 
        e.printStackTrace(); 
       } 

       Log.v(getPackageName(), "Stored in keystore"); 

       Toast setupComplete = Toast.makeText(getBaseContext(), "You have completed setup", Toast.LENGTH_SHORT); 
       setupComplete.show(); 
      } 
     } 
    } 

} 

package android.security; 

public class KeyStore { 
private boolean put(byte[] key, byte[] value) { 
    execute('i', key, value); 
    return mError == NO_ERROR; 
} 

public boolean put(String key, byte[] value) { 
    Log.v("KEYSTORE", "Attempting put"); 
    return put(getBytes(key), value); 
} 
} 

我得到的錯誤是.. 02-24 15:25:55.689:E/AndroidRuntime(11016):java.lang.NoSuchMethodError:android.security.KeyStore。把它放在onActivityResult()方法中。

如果您需要完整的logcat,我也可以發佈。

您可以看到我在代碼中植入了一些日誌消息。裏面放的那個從不打印出來。

編輯24/02/14: 以上NoMethod異常已經解決了通過移動KeyStore.java進入同一個包MainActivity.java - 謝謝你拉爾斯

但是我現在有一個新的問題。任何時候我嘗試使用ks.state()或ks.put(),我會得到AssertError的迴應:5 - 根據KeyStore.java,這是一個協議錯誤。

最終編輯 我想出了上述問題。原來我使用AOSP的KeyStore版本僅適用於4.2版以下的Android版本。

+0

可能是您的通話將您的字符串的getBytes不能被編碼和「的行爲此字符串不能在給定字符集中編碼時,此方法未指定。「也許針對UnsupportedEncodingException的檢查可能會顯示一些內容。 –

+0

你怎麼知道它在運行時確實存在? – lakshman

+0

對不起,這是我的錯誤措辭,我的意思是我在運行時出現錯誤,即使該方法確實存在。 – user3237636

回答

0

什麼是java.lang.NoSuchMethodError

Java文檔的原因說

Thrown if an application tries to call a specified method of a class (either static or instance), and that class no longer has a definition of that method. Normally, this error is caught by the compiler; this error can only occur at run time if the definition of a class has incompatibly changed.

在你的代碼

調用put方法在這裏

boolean success = ks.put("twofactorkey", resultBytes); 

,你有一個需要方法在KeyStore

但問題是你編譯的KeyStoreKeyStore.class文件)沒有要求的put方法。我假設你錯誤地改變了上面的放置方法,並且編譯了兩個類,並且運行MainActivity類。這就是爲什麼你得到那個錯誤

+0

嗨,感謝您的反饋,但我不認爲這是問題。我使用Eclipse並在保存每個文件時進行編譯。然後我運行包而不是單個文件。 我正在使用ZXIngLib,這工作正常。 – user3237636

0

當你在舊的虛擬機上運行一些代碼時會出現這種錯誤。 一般來說,當你的位碼調用一個不存在的函數時,這個appen就會變成這樣。

據我所知android.security;不存在,但java.security;呢。

如果您的自定義類,我不認爲你可以把它變成機器人的路徑,但我exoect一個編譯錯誤

+0

'android.security'由他定義 – lakshman

+0

你認爲這是什麼,然後http://developer.android.com/reference/android/security/package-summary.html? – NickT

+0

嗨,android.security.Keystore是由我定義的,取自AOSP。 – user3237636

相關問題