在将图像从Android应用程序发送到API时出现问题。我收到“ java.lang.RuntimeException:执行doInBackground()时发生错误”错误。请给我建议该怎么做。谢谢。
RecognizeConceptsActivity.java
package com.example.statistic.api.v2.activity;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.ViewSwitcher;
import com.example.statistic.R;
import com.example.statistic.api.v2.App;
import com.example.statistic.api.v2.ClarifaiUtil;
import com.example.statistic.api.v2.adapter.RecognizeConceptsAdapter;
import java.util.Collections;
import java.util.List;
import butterknife.BindView;
import butterknife.OnClick;
import clarifai2.api.ClarifaiResponse;
import clarifai2.dto.input.ClarifaiImage;
import clarifai2.dto.input.ClarifaiInput;
import clarifai2.dto.model.ConceptModel;
import clarifai2.dto.model.output.ClarifaiOutput;
import clarifai2.dto.prediction.Concept;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
public final class RecognizeConceptsActivity extends BaseActivity {
public static final int PICK_IMAGE = 100;
// the list of results that were returned from the API
@BindView(R.id.resultsList)
RecyclerView resultsList;
// the view where the image the user selected is displayed
@BindView(R.id.image2)
ImageView imageView;
// switches between the text prompting the user to hit the FAB, and the loading spinner
@BindView(R.id.switcher)
ViewSwitcher switcher;
// the FAB that the user clicks to select an image
@BindView(R.id.fab)
View fab;
@NonNull
private final RecognizeConceptsAdapter adapter = new RecognizeConceptsAdapter();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void onStart() {
super.onStart();
resultsList.setLayoutManager(new LinearLayoutManager(this));
resultsList.setAdapter(adapter);
}
@OnClick(R.id.fab)
void pickImage() {
startActivityForResult(new Intent(Intent.ACTION_PICK).setType("image/*"), PICK_IMAGE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) {
return;
}
switch(requestCode) {
case PICK_IMAGE:
final byte[] imageBytes = ClarifaiUtil.retrieveSelectedImage(this, data);
if (imageBytes != null) {
onImagePicked(imageBytes);
}
break;
}
}
private void onImagePicked(@NonNull final byte[] imageBytes) {
// Now we will upload our image to the Clarifai API
setBusy(true);
// Make sure we don't show a list of old concepts while the image is being uploaded
adapter.setData(Collections.<Concept>emptyList());
new AsyncTask<Void, Void, ClarifaiResponse<List<ClarifaiOutput<Concept>>>>() {
@Override
protected ClarifaiResponse<List<ClarifaiOutput<Concept>>> doInBackground(Void... params) {
// The default Clarifai model that identifies concepts in images
final ConceptModel generalModel = App.get().clarifaiClient().getDefaultModels().generalModel();
// Use this model to predict, with the image that the user just selected as the input
return generalModel.predict()
.withInputs(ClarifaiInput.forImage(ClarifaiImage.of(imageBytes)))
.executeSync();
}
@Override
protected void onPostExecute(ClarifaiResponse<List<ClarifaiOutput<Concept>>> response) {
setBusy(false);
if (!response.isSuccessful()) {
showErrorSnackbar(R.string.error_while_contacting_api);
return;
}
final List<ClarifaiOutput<Concept>> predictions = response.get();
if (predictions.isEmpty()) {
showErrorSnackbar(R.string.no_results_from_api);
return;
}
adapter.setData(predictions.get(0).data());
imageView.setImageBitmap(BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length));
}
private void showErrorSnackbar(@StringRes int errorString) {
Snackbar.make(
root,
errorString,
Snackbar.LENGTH_INDEFINITE
).show();
}
}.execute();
}
@Override
protected int layoutRes() { return R.layout.activity_recognize; }
private void setBusy(final boolean busy) {
runOnUiThread(new Runnable() {
@Override
public void run() {
switcher.setDisplayedChild(busy ? 1 : 0);
imageView.setVisibility(busy ? GONE : VISIBLE);
fab.setEnabled(!busy);
}
});
}
}
App.java
public class App extends Application {
// In a real app, rather than attaching singletons (such as the API client instance) to your Application instance,
// it's recommended that you use something like Dagger 2, and inject your client instance.
// Since that would be a distraction here, we will just use a regular singleton.
private static App INSTANCE;
@NonNull
public static App get() {
final App instance = INSTANCE;
if (instance == null) {
throw new IllegalStateException("App has not been created yet!");
}
return instance;
}
@Nullable
private ClarifaiClient client;
@Override
public void onCreate() {
INSTANCE = this;
client = new ClarifaiBuilder(getString(R.string.clarifai_api_key))
// Optionally customize HTTP client via a custom OkHttp instance
.client(new OkHttpClient.Builder()
.readTimeout(30, TimeUnit.SECONDS) // Increase timeout for poor mobile networks
// Log all incoming and outgoing data
// NOTE: You will not want to use the BODY log-level in production, as it will leak your API request details
// to the (publicly-viewable) Android log
.addInterceptor(new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String logString) {
Timber.e(logString);
}
}).setLevel(HttpLoggingInterceptor.Level.BODY))
.build()
)
.buildSync(); // use build() instead to get a Future<ClarifaiClient>, if you don't want to block this thread
super.onCreate();
// Initialize our logging
Timber.plant(new Timber.DebugTree());
}
@NonNull
public ClarifaiClient clarifaiClient() {
final ClarifaiClient client = this.client;
if (client == null) {
throw new IllegalStateException("Cannot use Clarifai client before initialized");
}
return client;
}
}
这是logcat错误
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: com.example.statistic, PID: 3451
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:325)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
Caused by: java.lang.IllegalStateException: App has not been created yet!
at com.example.statistic.api.v2.App.get(App.java:28)
at com.example.statistic.api.v2.activity.RecognizeConceptsActivity$1.doInBackground(RecognizeConceptsActivity.java:105)
at com.example.statistic.api.v2.activity.RecognizeConceptsActivity$1.doInBackground(RecognizeConceptsActivity.java:101)
at android.os.AsyncTask$2.call(AsyncTask.java:305)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
请告诉我该怎么做。谢谢