web-dev-qa-db-fra.com

Android IntentService ne peut pas instancier la classe; pas de constructeur vide

J'ai une classe MainActivity qui a besoin d'accéder à une API en ligne (utilisant ainsi des ressources réseau). Cela nécessite un thread d'arrière-plan que j'ai créé dans un fichier séparé HttpRequestService.Java.

MainActivity.Java:

public class MainActivity extends Activity {
    public static final String API_KEY = "KEYKEYKEYKEYKEY";
    public static final String CLIENT_ID = "IDIDIDIDIDIDID";
    private final String BROADCAST_ACTION = "com.example.BROADCAST";
    private final String EXTENDED_DATA_STATUS = "com.example.STATUS";
    static final String LOGCAT_TAG = "TAGTAGTAGTAGTAG";

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

    @Override
    protected void onResume() {
        super.onResume();

        String token = "TOKENTOKENTOKENTOKEN";
        String urlString = "https://www.example.com/api?key=" + API_KEY;

        // Create and start intent for HttpRequestService background thread.
        Intent httpRequestServiceIntent = new Intent(this, HttpRequestService.class);
        httpRequestServiceIntent.putExtra("token", token);
        httpRequestServiceIntent.putExtra("urlString", urlString);
        httpRequestServiceIntent.putExtra("client_id", CLIENT_ID);
        DownloadStateReceiver downloadStateReceiver = new DownloadStateReceiver();
        LocalBroadcastManager.getInstance(this).registerReceiver(downloadStateReceiver, new IntentFilter(BROADCAST_ACTION));
        this.startService(httpRequestServiceIntent);
    }

    private class DownloadStateReceiver extends BroadcastReceiver {
        // Broadcast receiver for receiving status updates from IntentService
        private DownloadStateReceiver() {
            // prevents instantiation
        }
        @Override
        public void onReceive(Context context, Intent intent) {
            String message = intent.getStringExtra(EXTENDED_DATA_STATUS);
            Log.d(LOGCAT_TAG, "onReceive received message: " + message);
            Toast.makeText(context, "Success!: " + message, Toast.LENGTH_LONG).show();
        }
    }

HttpRequestService.Java:

public final class HttpRequestService extends IntentService {

    public HttpRequestService(String name) {
        super(name);
        Log.e(LOGCAT_TAG, "You called the HttpRequestService directly. Don't do that. Call onHandleIntent.");
    }

    private final String LOGCAT_TAG = "HttpRequestService";
    private final String BROADCAST_ACTION = "com.genda.dayplanner.BROADCAST";
    private final String EXTENDED_DATA_STATUS = "com.genda.dayplanner.STATUS";

    @Override
    protected void onHandleIntent(Intent intent) {
        // Gets data from the incoming Intent
        String token = intent.getStringExtra("token");
        String urlString = intent.getStringExtra("urlString");
        String client_id = intent.getStringExtra("client_id");
        Boolean extraError = false;
        if (token == null) {
            Log.e(LOGCAT_TAG, "Intent didn't contain required token.");
            extraError = true;
        }
        if (urlString == null) {
            Log.e(LOGCAT_TAG, "Intent didn't contain required urlBundle.");
            extraError = true;
        }
        if (client_id == null) {
            Log.e(LOGCAT_TAG, "Intent didn't contain required client_id.");
            extraError = true;
        }
        if (extraError == true) {
            // error response
        }

        // Now do request

        URL url = null;
        try {
            url = new URL(urlString);
        } catch (MalformedURLException e) {
            Log.e(LOGCAT_TAG, "The URL for requesting the tasks API was malformed.");
        }
        HttpURLConnection conn = null;
        try {
            conn = (HttpURLConnection) url.openConnection();
        } catch (IOException e) {
            Log.e(LOGCAT_TAG, "Bad connection to the API URL");
        }
        conn.addRequestProperty("client_id", client_id);
        conn.setRequestProperty("Authorization", "OAuth " + token);
        String result = null;
        try {
            InputStream in = new BufferedInputStream(conn.getInputStream());
            result = convertStreamToString(in);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            conn.disconnect();
        }

        // Create new Intent with URI object
        Intent localIntent = new Intent(BROADCAST_ACTION);
        localIntent.putExtra(EXTENDED_DATA_STATUS, result);
        // Broadcasts intent to receivers in this app.
        LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
    }

    public static String convertStreamToString(InputStream in) {
        // Use BufferedReader.readLine() method. Iterate until BufferedReader returns null (no more data to read). Each line appended to StringBuilder.
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        StringBuilder sb = new StringBuilder();
        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }
}

Voici le LogCat:

09-21 17:15:28.157: D/dalvikvm(11055): newInstance failed: no <init>()
09-21 17:15:28.157: D/AndroidRuntime(11055): Shutting down VM
09-21 17:15:28.157: W/dalvikvm(11055): threadid=1: thread exiting with uncaught exception (group=0x41f3b700)
09-21 17:15:28.167: E/AndroidRuntime(11055): FATAL EXCEPTION: main
09-21 17:15:28.167: E/AndroidRuntime(11055): Java.lang.RuntimeException: Unable to instantiate service com.example.HttpRequestService: Java.lang.InstantiationException: can't instantiate class com.example.HttpRequestService; no empty constructor
09-21 17:15:28.167: E/AndroidRuntime(11055):    at Android.app.ActivityThread.handleCreateService(ActivityThread.Java:2561)
09-21 17:15:28.167: E/AndroidRuntime(11055):    at Android.app.ActivityThread.access$1600(ActivityThread.Java:141)
09-21 17:15:28.167: E/AndroidRuntime(11055):    at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:1338)
09-21 17:15:28.167: E/AndroidRuntime(11055):    at Android.os.Handler.dispatchMessage(Handler.Java:99)
09-21 17:15:28.167: E/AndroidRuntime(11055):    at Android.os.Looper.loop(Looper.Java:137)
09-21 17:15:28.167: E/AndroidRuntime(11055):    at Android.app.ActivityThread.main(ActivityThread.Java:5103)
09-21 17:15:28.167: E/AndroidRuntime(11055):    at Java.lang.reflect.Method.invokeNative(Native Method)
09-21 17:15:28.167: E/AndroidRuntime(11055):    at Java.lang.reflect.Method.invoke(Method.Java:525)
09-21 17:15:28.167: E/AndroidRuntime(11055):    at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:737)
09-21 17:15:28.167: E/AndroidRuntime(11055):    at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:553)
09-21 17:15:28.167: E/AndroidRuntime(11055):    at dalvik.system.NativeStart.main(Native Method)
09-21 17:15:28.167: E/AndroidRuntime(11055): Caused by: Java.lang.InstantiationException: can't instantiate class com.example.HttpRequestService; no empty constructor
09-21 17:15:28.167: E/AndroidRuntime(11055):    at Java.lang.Class.newInstanceImpl(Native Method)
09-21 17:15:28.167: E/AndroidRuntime(11055):    at Java.lang.Class.newInstance(Class.Java:1130)
09-21 17:15:28.167: E/AndroidRuntime(11055):    at Android.app.ActivityThread.handleCreateService(ActivityThread.Java:2558)
09-21 17:15:28.167: E/AndroidRuntime(11055):    ... 10 more

La partie importante, je pense, est le can't instantiate class com.example.HttpRequestService; no empty constructor. J'ai vu plusieurs autres discussions similaires à cela, mais ils ont tous pu résoudre le problème parce que leur classe est une sous-classe de leur MainActivity. Ils rendent donc la sous-classe statique et cela résout le problème. Malheureusement, une classe distincte HttpRequestService ne peut pas être statique. Aucune suggestion?

23
Kyle

Exception vous indique que vous devez implémenter le constructeur public par défaut.

  public HttpRequestService() {
    super("Name for Service");
       }

le constructeur public par défaut est un constructeur sans paramètres.

Ici, vous appelez super() et passez un String qui sera utilisé pour nommer le IntentService

57
Emmanuel

Une autre chose à garder à l'esprit: si vous avez votre service en tant que classe imbriquée, il doit être statique.

Compare intentservice pas de constructeur vide, mais il y a un constructeur

13
thomasd