Java 我的android设备上运行时确实存在的方法上的NoSuchMethodError
感谢您抽出时间阅读此文章。我在一个涉及Android的项目中遇到了一个非常奇怪的“NoSuchMethodError”。我无法理解这一点,因为它违背了我所有的逻辑Java 我的android设备上运行时确实存在的方法上的NoSuchMethodError,java,android,qr-code,nosuchmethoderror,Java,Android,Qr Code,Nosuchmethoderror,感谢您抽出时间阅读此文章。我在一个涉及Android的项目中遇到了一个非常奇怪的“NoSuchMethodError”。我无法理解这一点,因为它违背了我所有的逻辑 package com.project.qrcode import android.security.KeyStore; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingExcept
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();
}
}
}
}
我得到的错误是。。
02-24 15:25:55.689:E/AndroidRuntime(11016):java.lang.NoSuchMethodError:android.security.KeyStore.put,发生在onActivityResult()方法中
如果你需要完整的日志,我也可以发布
您可以看到我在代码中植入了一些日志消息。里面的那个永远不会打印出来
2014年2月24日编辑:
通过将KeyStore.java移动到与MainActivity.java相同的包中,上述NoMethod异常已得到解决-谢谢Lars
然而,我现在有一个新问题。每当我尝试使用ks.state()或ks.put()时,我都会收到AssertError:5的响应—根据KeyStore.java,这是一个协议错误
最终编辑
我解决了上面的问题。我从AOSP使用的密钥库版本仅适用于4.2以下的Android版本。java.lang.NoSuchMethodError的原因是什么 java博士说 当应用程序试图调用类的指定方法时引发 (静态或实例),并且该类不再具有定义 这种方法的优点。通常,编译器会捕获此错误;这 仅当类的定义已更改时,才会在运行时发生错误 无可比拟的变化 在代码中,您在此处调用put方法
boolean success = ks.put("twofactorkey", resultBytes);
在KeyStore
类中有一个必需的方法
public boolean put(String key, byte[] value) {
Log.v("KEYSTORE", "Attempting put");
return put(getBytes(key), value);
}
但问题是编译的
密钥库(KeyStore.class
文件)没有必需的put方法。我假设您错误地更改了上述put方法,并且单独编译了两个类,并运行了MainActivity
类。这就是为什么会出现这样的错误在较旧的虚拟机上运行某些代码时会出现这样的错误。
通常,当您的位代码调用不存在的函数时,会出现这种情况
据我所知,android.security
不存在,但java.security代码>可以
如果这是您的自定义类,我不认为您可以将其放入android的路径中,但我发现编译错误android.security
由他定义,那么您认为这是什么?嗨,android.security.Keystore由我定义并取自AOSP。您在哪里实现execute(…)?顺便说一句,除非修改VM文件,否则我不认为您可以将自己的类放入android.security包中。我想既然您从AOSP获取了密钥库类,您就没有更改包名。如果android本身在引导过程中首先加载相同的类,那么您的类将不会被加载。它将存在于编译时,但不存在于运行时,因为已加载的密钥库类将是使用的密钥库类,并且该类可能没有put()方法。可能无法对字符串上的getBytes调用进行编码,并且“无法在给定的字符集中对该字符串进行编码时,该方法的行为未指定。”也许对不支持的编码异常进行检查可以显示一些情况。您如何知道它在运行时确实存在?很抱歉,我的说法不正确,我的意思是,即使该方法确实存在,我也会在运行时收到错误。您好,感谢您的反馈,但我不相信这是问题所在。我使用的是Eclipse,保存后会编译每个文件。然后我运行包而不是单个文件。我用的是ZXIngLib,效果很好。
public boolean put(String key, byte[] value) {
Log.v("KEYSTORE", "Attempting put");
return put(getBytes(key), value);
}