简体   繁体   中英

Android: What is the best way to implement a synchronization service (via http post) in background (service)

Here is my last implementation of a basic Service used to sync data between a web service (with some HTTP POST request).

Basically, during application execution, I want to continue sending post (every 1 minute) to my web service.

package com.example.testservice;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

public class HelloService 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) {
            // empty
        }
    }

    @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",
                android.os.Process.THREAD_PRIORITY_BACKGROUND);
        thread.start();

        // Get the HandlerThread's Looper and use it for our Handler
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);

        Log.d("SERVICE TEST onCreate", "Service created first time");
        Toast.makeText(this, "service created", Toast.LENGTH_SHORT).show();
        final long oneMinuteMs = 60 * 1000;
        Runnable eachMinute = new Runnable() {
            @Override
            public void run() {
                Log.d("SERVICE TEST run", "Each minute task executing");
                mServiceHandler.postDelayed(this, oneMinuteMs);
            }
        };

        mServiceHandler.postDelayed(eachMinute, oneMinuteMs);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // empty
        // If we get killed, after returning from here, restart
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        // We don't provide binding, so return null
        return null;
    }

    @Override
    public void onDestroy() {
        Log.d("SERVICE TEST onDestroy", "Service destroyed");
    }
}
  • Is this the better way in Android?
  • Is it correct to use onCreate method to ensure one single sync task will be started for the duration of the app life?
  • Is it correct to start the service from my first activity (MainActivity)?

The code:

package com.ncfsistemi.testservice;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent(this, HelloService.class);
        startService(intent);       
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

Note: I've also tried with

TimerTask syncTask = new TimerTask()

but I've got some strange behaviour (task spawned multiple times and with wrong time control). TimerTask is discouraged by Android creators... correct?

If you want to sync data periodically based on some schedule, the best approach is to use SyncAdapter . Take a look at the documentation, there are good examples how to use it.

If you want to sync the data on demand (for example on activity's onResume method), you can use an IntentService .

No matter what you do, do not run TimerTask . As you have found by yourself, unexpected behavior may occur. You can read here about how processes and threads are managed under Android OS and see that it is likely the TimerTask to be killed. For http opperations you have to use Service s because of their high priority.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM