这里的课程:
VoiceApplication类 用于在第一次启动时初始化数据库,并在插入模式时提供模式的ID,我从gitorious获取此代码并对其进行修改。
public class VoiceApplication extends Application {
private static final String TAG = "VoiceAuth";
private static final String PREF_KEY_MODE_ID = "modeId";
@Override
public void onCreate() {
super.onCreate();
initAuthMethod();
}
/**
* Returns the unique ID of this authentication mode that was returned when
* this authentication mode was first inserted into the database.
* @return
*/
public long getModeId() {
return PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getLong(PREF_KEY_MODE_ID, -1);
}
private void initAuthMethod() {
if (!voiceAuthMethodExists()) {
createAuthMethod();
}
}
private void createAuthMethod() {
Log.d(TAG, "Creating auth method with values: " + ContentValueDefaults.DEFAULT_CONTENT_VALUES.toString());
Uri insertedUri = getContentResolver().insert(Mode.CONTENT_URI, ContentValueDefaults.DEFAULT_CONTENT_VALUES);
long modeId = ContentUris.parseId(insertedUri);
Log.v(TAG, "Storing modeId in preferences: " + modeId);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
prefs.edit().putLong(PREF_KEY_MODE_ID, modeId).commit();
}
private boolean voiceAuthMethodExists() {
String[] projection = {
Mode.NAME
};
String selection = Mode.NAME + " = ?";
String[] selectionArgs = {
ContentValueDefaults.UNIQUE_NAME
};
Cursor c = getContentResolver().query(Mode.CONTENT_URI, projection, selection, selectionArgs, null);
if (!c.moveToFirst())
return false;
String existingName = c.getString(c.getColumnIndexOrThrow(Mode.NAME));
return ContentValueDefaults.UNIQUE_NAME.equals(existingName);
}
}
用于初始化数据库的ContentValueDefaults类
public final class ContentValueDefaults {
public static final String MODE_TYPE = AuthModes.VOICE_RECOGNITION;
public static final String UNIQUE_NAME = "com.neu.val.activity.VoiceAuthenticator";
public static final String DISPLAY_NAME = "Voice Authentication";
public static ContentValues DEFAULT_CONTENT_VALUES;
static {
DEFAULT_CONTENT_VALUES = new ContentValues();
DEFAULT_CONTENT_VALUES.put(Mode.NAME, UNIQUE_NAME);
DEFAULT_CONTENT_VALUES.put(Mode.TYPE, MODE_TYPE);
DEFAULT_CONTENT_VALUES.put(Mode.DISPLAY_NAME, DISPLAY_NAME);
DEFAULT_CONTENT_VALUES.put(Mode.PACKAGE_NAME, "com.neu.val.activity");
DEFAULT_CONTENT_VALUES.put(Mode.CLASS_NAME, ".VoiceAuthenticator.java");
}
}
VoiceAuthenticator类使用保存的密码验证用户输入的密码,如果尚未存在密码,则重定向到密码创建活动
public class VoiceAuthenticator extends Activity implements OnClickListener {
private static final int MAX_DURATION = 2500;
public static final String TAG = "VoiceAuth";
private static final double THRESHOLD = 10000;
private int seconds, progressTime;
private Uri userUri;
private ProgressBar progressBar;
private Button btnStartRecording, btnCancel;
private WaveRecorder waveRecorder;
public FeatureVector userFeatureVector;
private static File outputFile =
new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC),
"recording.wav");
private Timer timer;
private boolean stopped;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.voiceauth);
userUri = getIntent().getData();
// this just for testing
if (userUri == null) {
finish();
return;
}
if (!checkUserStillExists()) {
UIUtils.showErrorDialog(
this,
"User deleted",
"The requested user does not exist anymore, authentication will not be possible!",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
return;
}
checkFeaturesExist();
}
@SuppressWarnings("deprecation")
private boolean checkUserStillExists() {
Cursor c = managedQuery(userUri, null, null, null, null);
return c.getCount() > 0;
}
@SuppressWarnings("deprecation")
private void checkFeaturesExist() {
long userId = ContentUris.parseId(userUri);
long modeId = ((VoiceApplication) getApplication()).getModeId();
Uri featuresUri = Feature.buildFeaturesForSubjectAndMode(userId, modeId);
Cursor c = managedQuery(featuresUri, null, null, null, null);
if (c.getCount() == 0) {
askToCreateFeatures();
} else {
setupUi();
}
}
public void startProgress() {
final Handler handler = new Handler();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
handler.post(new Runnable() {
@Override
public void run() {
try {
progress();
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
});
}
};
timer = new Timer();
timer.schedule(timerTask, 1, 1000);
}
public void progress() {
if (!stopped) // call ui only when the progress is not stopped
{
if (progressTime < MAX_DURATION) {
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
progressTime = progressBar.getProgress() + 1000;
progressBar.setProgress(progressTime);
seconds += 1000;
} catch (Exception e) {
}
}
});
} else {
stopRecord();
}
}
}
private void askToCreateFeatures() {
AlertDialog.Builder builder = new Builder(this);
builder.setTitle("Unknown user");
builder.setMessage("No voice features for this user yet, do you want to record features now?");
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(VoiceAuthenticator.this, CreateVoiceSample.class);
long userId = ContentUris.parseId(userUri);
intent.putExtra(Extras.EXTRA_USER_ID, userId);
startActivity(intent);
finish();
}
});
builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
finish();
}
});
builder.show();
}
/**
* Loads user info from the content resolver and sets up button listener.
*/
private void setupUi() {
btnStartRecording = (Button) findViewById(R.id.bSpeak);
btnCancel = (Button) findViewById(R.id.bCancel);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
progressBar.setMax(MAX_DURATION);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bSpeak:
startRecording();
checkResults();
break;
case R.id.bCancel:
finish();
break;
default:
break;
}
}
private void startRecording() {
seconds = 1000;
progressTime = 0;
progressBar.setProgress(0);
if (outputFile.exists()) outputFile.delete();
btnStartRecording.setEnabled(false);
waveRecorder = new WaveRecorder(8000);
waveRecorder.setOutputFile(outputFile.getAbsolutePath());
stopped = false;
try {
waveRecorder.prepare();
waveRecorder.start();
Toast.makeText(getApplicationContext(), "Recording started ... ",
Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
}
public void stopRecord() {
stopped = true;
waveRecorder.stop();
waveRecorder.release();
waveRecorder.reset();
timer.cancel();
Toast.makeText(getApplicationContext(), "Recording stopped..", Toast.LENGTH_SHORT).show();
startProgress();
checkResults();
}
private void checkResults() {
Cursor allCodebooksCursor = queryAllCodebooks();
long claimedUserId = ContentUris.parseId(userUri);
long bestUserId = -1;
Log.i(TAG, "Starting to check voice features for userId=" + claimedUserId);
double minAverageDistortion = Double.MAX_VALUE;
if (allCodebooksCursor.moveToFirst()) {
do {
long currentUserId = allCodebooksCursor.getLong(allCodebooksCursor.getColumnIndexOrThrow(Feature.SUBJECT_ID));
Codebook codebook = getCodebookForUser(allCodebooksCursor);
double averageDistortion = ClusterUtil.calculateAverageDistortion(
userFeatureVector, codebook);
Log.d(TAG, "Calculated avg distortion for userId " + currentUserId + " =" + averageDistortion);
if (averageDistortion < minAverageDistortion) {
minAverageDistortion = averageDistortion;
bestUserId = currentUserId;
}
} while (allCodebooksCursor.moveToNext());
}
if (minAverageDistortion <= THRESHOLD && claimedUserId == bestUserId) {
returnSuccess(minAverageDistortion);
} else {
returnFailure();
}
}
private Codebook getCodebookForUser(Cursor cursor) {
Gson gson = new Gson();
String representation = cursor.getString(cursor
.getColumnIndexOrThrow(Feature.REPRESENTATION));
Codebook codebook = gson.fromJson(representation,
Codebook.class);
return codebook;
}
private Cursor queryAllCodebooks() {
long modeId = ((VoiceApplication) getApplication()).getModeId();
Uri uri = Feature.buildFeaturesForMode(modeId);
String[] columns = {
Feature.SUBJECT_ID,
Feature.REPRESENTATION
};
Cursor cursor = managedQuery(uri, columns, null, null, null);
return cursor;
}
private void returnFailure() {
Intent resultIntent = new Intent();
resultIntent.putExtra(Extras.EXTRA_RESULT, false);
resultIntent.putExtra(Extras.EXTRA_RESULT_CONFIDENCE, 0.0d);
setResult(RESULT_OK, resultIntent);
finish();
}
private void returnSuccess(double minAverageDistortion) {
Intent resultIntent = new Intent();
resultIntent.putExtra(Extras.EXTRA_RESULT, true);
resultIntent.putExtra(Extras.EXTRA_RESULT_CONFIDENCE, minAverageDistortion);
setResult(RESULT_OK, resultIntent);
finish();
}
class MfccTask extends AsyncTask<String, Object, FeatureVector> {
private ProgressDialog progressDialog;
private final Activity parentActivity;
public MfccTask(Activity parentActivity) {
this.parentActivity = parentActivity;
}
@Override
protected FeatureVector doInBackground(String... params) {
String filename = params[0];
WavReader wavReader = new WavReader(filename);
Log.i(TAG, "Starting to read from file " + filename);
double[] samples = readSamples(wavReader);
Log.i(TAG, "Starting to calculate MFCC");
double[][] mfcc = calculateMfcc(samples);
FeatureVector pl = createFeatureVector(mfcc);
return pl;
}
private FeatureVector createFeatureVector(double[][] mfcc) {
int vectorSize = mfcc[0].length;
int vectorCount = mfcc.length;
Log.i(TAG, "Creating pointlist with dimension=" + vectorSize + ", count=" + vectorCount);
FeatureVector pl = new FeatureVector(vectorSize, vectorCount);
for (int i = 0; i < vectorCount; i++) {
pl.add(mfcc[i]);
}
Log.d(CreateVoiceSample.TAG, "Added all MFCC vectors to pointlist");
return pl;
}
private short createSample(byte[] buffer) {
short sample = 0;
// hardcoded two bytes here
short b1 = buffer[0];
short b2 = buffer[1];
b2 <<= 8;
sample = (short) (b1 | b2);
return sample;
}
private double[][] calculateMfcc(double[] samples) {
MFCC mfccCalculator = new MFCC(Constants.SAMPLERATE, Constants.WINDOWSIZE,
Constants.COEFFICIENTS, false, Constants.MINFREQ + 1, Constants.MAXFREQ, Constants.FILTERS);
int hopSize = Constants.WINDOWSIZE / 2;
int mfccCount = (samples.length / hopSize) - 1;
double[][] mfcc = new double[mfccCount][Constants.COEFFICIENTS];
long start = System.currentTimeMillis();
for (int i = 0, pos = 0; pos < samples.length - hopSize; i++, pos += hopSize) {
mfcc[i] = mfccCalculator.processWindow(samples, pos);
if (i % 20 == 0) {
publishProgress("Calculating features...", i, mfccCount);
}
}
publishProgress("Calculating features...", mfccCount, mfccCount);
Log.i(TAG, "Calculated " + mfcc.length + " vectors of MFCCs in "
+ (System.currentTimeMillis() - start) + "ms");
return mfcc;
}
private double[] readSamples(WavReader wavReader) {
int sampleSize = wavReader.getFrameSize();
int sampleCount = wavReader.getPayloadLength() / sampleSize;
int windowCount = (int) Math.floor(sampleCount / Constants.WINDOWSIZE);
byte[] buffer = new byte[sampleSize];
double[] samples = new double[windowCount
* Constants.WINDOWSIZE];
try {
for (int i = 0; i < samples.length; i++) {
wavReader.read(buffer, 0, sampleSize);
samples[i] = createSample(buffer);
if (i % 1000 == 0) {
publishProgress("Reading samples...", i, samples.length);
}
}
} catch (IOException e) {
Log.e(CreateVoiceSample.TAG, "Exception in reading samples", e);
}
return samples;
}
@Override
protected void onPostExecute(FeatureVector result) {
progressDialog.dismiss();
userFeatureVector = result;
}
@Override
protected void onPreExecute() {
progressDialog = new ProgressDialog(parentActivity);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setTitle("Working...");
progressDialog.setMessage("Working...");
progressDialog.setProgress(0);
progressDialog.setMax(10000);
progressDialog.show();
progressDialog.setCancelable(false);
progressDialog.setCanceledOnTouchOutside(false);
}
@Override
protected void onProgressUpdate(Object... values) {
String msg = (String) values[0];
Integer current = (Integer) values[1];
Integer max = (Integer) values[2];
progressDialog.setMessage(msg);
progressDialog.setProgress(current);
progressDialog.setMax(max);
}
}
}
的AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.neu.val.activity"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="16" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:name=".VoiceApplication">
<activity
android:name=".MainActivity"
android:clearTaskOnLaunch="true"
android:excludeFromRecents="true"
android:label="@string/app_name"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".CreateVoiceSample"
android:label="@string/app_name" >
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.INSERT" />
<data android:mimeType="vnd.android.cursor.dir/vnd.hgb.feature" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.DEFAULT" />
<category android:name="com.neu.val.activity.CREATEVOICESAMPLE" />
</intent-filter>
</activity>
<activity
android:name=".VoiceAuthenticator"
android:label="@string/app_name" >
<intent-filter >
<action android:name="com.neu.val.intent.AUTH_METHOD" />
</intent-filter>
<intent-filter>
<action android:name="com.neu.val.intent.DO_AUTH.voicerecognition"/>
</intent-filter>
</activity>
<service android:name="com.neu.val.service.LockService" >
</service>
<receiver
android:name="com.neu.val.service.BootStartUpReceiver"
android:enabled="true"
android:exported="false" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<provider
android:name="com.neu.val.database.AuthDb"
android:authorities="com.neu.val.database">
</provider>
</application>
</manifest>
和logcat
01-31 15:18:08.159: D/AndroidRuntime(9582): Shutting down VM
01-31 15:18:08.159: W/dalvikvm(9582): threadid=1: thread exiting with uncaught exception (group=0x41c72da0)
01-31 15:18:08.159: E/AndroidRuntime(9582): FATAL EXCEPTION: main
01-31 15:18:08.159: E/AndroidRuntime(9582): Process: com.neu.val.activity, PID: 9582
01-31 15:18:08.159: E/AndroidRuntime(9582): java.lang.RuntimeException: Unable to create application com.neu.val.activity.VoiceApplication: java.lang.NullPointerException
01-31 15:18:08.159: E/AndroidRuntime(9582): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4752)
01-31 15:18:08.159: E/AndroidRuntime(9582): at android.app.ActivityThread.access$1600(ActivityThread.java:172)
01-31 15:18:08.159: E/AndroidRuntime(9582): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1368)
01-31 15:18:08.159: E/AndroidRuntime(9582): at android.os.Handler.dispatchMessage(Handler.java:102)
01-31 15:18:08.159: E/AndroidRuntime(9582): at android.os.Looper.loop(Looper.java:146)
01-31 15:18:08.159: E/AndroidRuntime(9582): at android.app.ActivityThread.main(ActivityThread.java:5653)
01-31 15:18:08.159: E/AndroidRuntime(9582): at java.lang.reflect.Method.invokeNative(Native Method)
01-31 15:18:08.159: E/AndroidRuntime(9582): at java.lang.reflect.Method.invoke(Method.java:515)
01-31 15:18:08.159: E/AndroidRuntime(9582): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
01-31 15:18:08.159: E/AndroidRuntime(9582): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
01-31 15:18:08.159: E/AndroidRuntime(9582): at dalvik.system.NativeStart.main(Native Method)
01-31 15:18:08.159: E/AndroidRuntime(9582): Caused by: java.lang.NullPointerException
01-31 15:18:08.159: E/AndroidRuntime(9582): at com.neu.val.activity.VoiceApplication.voiceAuthMethodExists(VoiceApplication.java:78)
01-31 15:18:08.159: E/AndroidRuntime(9582): at com.neu.val.activity.VoiceApplication.initAuthMethod(VoiceApplication.java:54)
01-31 15:18:08.159: E/AndroidRuntime(9582): at com.neu.val.activity.VoiceApplication.onCreate(VoiceApplication.java:41)
01-31 15:18:08.159: E/AndroidRuntime(9582): at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1013)
01-31 15:18:08.159: E/AndroidRuntime(9582): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4749)
01-31 15:18:08.159: E/AndroidRuntime(9582): ... 10 more
01-31 15:18:09.989: I/Process(9582): Sending signal. PID: 9582 SIG: 9
01-31 15:18:10.099: D/AndroidRuntime(9705): Shutting down VM
01-31 15:18:10.099: W/dalvikvm(9705): threadid=1: thread exiting with uncaught exception (group=0x41c72da0)
01-31 15:18:10.099: E/AndroidRuntime(9705): FATAL EXCEPTION: main
01-31 15:18:10.099: E/AndroidRuntime(9705): Process: com.neu.val.activity, PID: 9705
01-31 15:18:10.099: E/AndroidRuntime(9705): java.lang.RuntimeException: Unable to create application com.neu.val.activity.VoiceApplication: java.lang.NullPointerException
01-31 15:18:10.099: E/AndroidRuntime(9705): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4752)
01-31 15:18:10.099: E/AndroidRuntime(9705): at android.app.ActivityThread.access$1600(ActivityThread.java:172)
01-31 15:18:10.099: E/AndroidRuntime(9705): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1368)
01-31 15:18:10.099: E/AndroidRuntime(9705): at android.os.Handler.dispatchMessage(Handler.java:102)
01-31 15:18:10.099: E/AndroidRuntime(9705): at android.os.Looper.loop(Looper.java:146)
01-31 15:18:10.099: E/AndroidRuntime(9705): at android.app.ActivityThread.main(ActivityThread.java:5653)
01-31 15:18:10.099: E/AndroidRuntime(9705): at java.lang.reflect.Method.invokeNative(Native Method)
01-31 15:18:10.099: E/AndroidRuntime(9705): at java.lang.reflect.Method.invoke(Method.java:515)
01-31 15:18:10.099: E/AndroidRuntime(9705): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
01-31 15:18:10.099: E/AndroidRuntime(9705): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
01-31 15:18:10.099: E/AndroidRuntime(9705): at dalvik.system.NativeStart.main(Native Method)
01-31 15:18:10.099: E/AndroidRuntime(9705): Caused by: java.lang.NullPointerException
01-31 15:18:10.099: E/AndroidRuntime(9705): at com.neu.val.activity.VoiceApplication.voiceAuthMethodExists(VoiceApplication.java:78)
01-31 15:18:10.099: E/AndroidRuntime(9705): at com.neu.val.activity.VoiceApplication.initAuthMethod(VoiceApplication.java:54)
01-31 15:18:10.099: E/AndroidRuntime(9705): at com.neu.val.activity.VoiceApplication.onCreate(VoiceApplication.java:41)
01-31 15:18:10.099: E/AndroidRuntime(9705): at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1013)
01-31 15:18:10.099: E/AndroidRuntime(9705): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4749)
01-31 15:18:10.099: E/AndroidRuntime(9705): ... 10 more
01-31 15:18:12.029: D/AndroidRuntime(9921): Shutting down VM
01-31 15:18:12.029: W/dalvikvm(9921): threadid=1: thread exiting with uncaught exception (group=0x41c72da0)
01-31 15:18:12.029: E/AndroidRuntime(9921): FATAL EXCEPTION: main
01-31 15:18:12.029: E/AndroidRuntime(9921): Process: com.neu.val.activity, PID: 9921
01-31 15:18:12.029: E/AndroidRuntime(9921): java.lang.RuntimeException: Unable to create application com.neu.val.activity.VoiceApplication: java.lang.NullPointerException
01-31 15:18:12.029: E/AndroidRuntime(9921): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4752)
01-31 15:18:12.029: E/AndroidRuntime(9921): at android.app.ActivityThread.access$1600(ActivityThread.java:172)
01-31 15:18:12.029: E/AndroidRuntime(9921): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1368)
01-31 15:18:12.029: E/AndroidRuntime(9921): at android.os.Handler.dispatchMessage(Handler.java:102)
01-31 15:18:12.029: E/AndroidRuntime(9921): at android.os.Looper.loop(Looper.java:146)
01-31 15:18:12.029: E/AndroidRuntime(9921): at android.app.ActivityThread.main(ActivityThread.java:5653)
01-31 15:18:12.029: E/AndroidRuntime(9921): at java.lang.reflect.Method.invokeNative(Native Method)
01-31 15:18:12.029: E/AndroidRuntime(9921): at java.lang.reflect.Method.invoke(Method.java:515)
01-31 15:18:12.029: E/AndroidRuntime(9921): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
01-31 15:18:12.029: E/AndroidRuntime(9921): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
01-31 15:18:12.029: E/AndroidRuntime(9921): at dalvik.system.NativeStart.main(Native Method)
01-31 15:18:12.029: E/AndroidRuntime(9921): Caused by: java.lang.NullPointerException
01-31 15:18:12.029: E/AndroidRuntime(9921): at com.neu.val.activity.VoiceApplication.voiceAuthMethodExists(VoiceApplication.java:78)
01-31 15:18:12.029: E/AndroidRuntime(9921): at com.neu.val.activity.VoiceApplication.initAuthMethod(VoiceApplication.java:54)
01-31 15:18:12.029: E/AndroidRuntime(9921): at com.neu.val.activity.VoiceApplication.onCreate(VoiceApplication.java:41)
01-31 15:18:12.029: E/AndroidRuntime(9921): at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1013)
01-31 15:18:12.029: E/AndroidRuntime(9921): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4749)
01-31 15:18:12.029: E/AndroidRuntime(9921): ... 10 more
01-31 15:18:13.849: I/Process(9921): Sending signal. PID: 9921 SIG: 9
答案 0 :(得分:0)
像这样改变这个集团:
if(c != null){
if (!c.moveToFirst())
return false;
String existingName = c.getString(c.getColumnIndexOrThrow(Mode.NAME));
return ContentValueDefaults.UNIQUE_NAME.equals(existingName);
} else {
// return the boolean value if your cursor is null
}