Reputation: 201
I am using an AsyncTask in my Service so i can call multiple urls. I am not sure how i can handle calling urls in a single service. This is my current solution:
public int onStartCommand(Intent intent, int flags, int startId) {
SharedPreferences preferences = getSharedPreferences("data", MODE_PRIVATE);
String apiKey = preferences.getString("apiKey", null);
FetchData data = new FetchData();
data.execute("travel", apiKey);
FetchData otherData = new FetchData();
otherData.execute("notifications",apiKey);
FetchData barData = new FetchData();
barData.execute("bars", apiKey);
checkData();
return START_STICKY;
}
This is my ASyncTask doInBackgroud calling different urls:
protected String[] doInBackground(String... params) {
HttpURLConnection urlConnection = null;
BufferedReader reader= null;
String data = null;
try {
selection = params[0];
//url for the data fetch
URL url = new URL("http://api.torn.com/user/?selections="+selection+"&key=*****");
//gets the http result
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
//reads the data into an input file...maybe
InputStream inputStream = urlConnection.getInputStream();
StringBuilder buffer = new StringBuilder();
if (inputStream == null) {
return null;
}
//does something important
reader = new BufferedReader(new InputStreamReader(inputStream));
//reads the reader up above
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line).append("\n");
}
if (buffer.length() == 0) {
return null;
}
data = buffer.toString();
} catch (IOException e) {
return null;
}
finally{
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException ignored) {
}
}
}
how am not sure if i'm even supposed to use ASyncTask in a Service. Can anyone tell me what is the correct way of handle this situation
Upvotes: 3
Views: 1255
Reputation: 2509
You don't need to implement an AsyncTask
. You should create a class that extends Service
, this class will handle it's own message queue and create a separate thread for each message it receives. For example:
public class MyNetworkService extends Service {
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
// Handler that receives messages from the thread
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
// Obtain your url from your data bundle, passed from the start intent.
Bundle data = msg.getData();
// Get your url string and api key.
String action = data.getString("action");
String apiKey = data.getString("apiKey");
//
//
// Open your connection here.
//
//
// Stop the service using the startId, so that we don't stop
// the service in the middle of handling another job
stopSelf(msg.arg1);
}
}
@Override
public void onCreate() {
// Start up the thread running the service. Note that we create a
// separate thread because the service normally runs in the process's
// main thread, which we don't want to block. We also make it
// background priority so CPU-intensive work will not disrupt our UI.
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
// Retrieve your bundle from your intent.
Bundle data = intent.getExtras();
// For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the job
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
// Set the message data as your intent bundle.
msg.setData(data);
mServiceHandler.sendMessage(msg);
// If we get killed, after returning from here, restart
return START_STICKY;
}
}
Once your service is set up, you can define that service in your manifest.
<service android:name=".MyNetworkService" />
In your activity, or wherever you feel it would be necessary, you can start the service using startService()
, for example.
// Create the intent.
Intent travelServiceIntent = new Intent(this, MyNetworkService.class);
// Create the bundle to pass to the service.
Bundle data = new Bundle();
data.putString("action", "travel");
data.putString("apiKey", apiKey);
// Add the bundle to the intent.
travelServiceIntent.putExtras(data);
// Start the service.
startService(travelServiceIntent); // Call this for each URL connection you make.
If you want to bind the service and communicate with it from the UI thread, you need to implement an IBinder interface and call bindService()
instead of startService()
.
Check out Bound Services.
Hope this helps.
Upvotes: 1