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
.
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();
}
}
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();
}
}
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?
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
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