Android service runs only the first time

Asked

Viewed 152 times

3

I am developing an application where synchronization is done with a web services. The application is very simple, makes a list of questions, the user responds, when clicking finish, records this data in the cellular database, and makes the replication, because it may be connected to the internet or not.

My problem is this, every first time I open the system and do the whole process, everything works perfectly, synchronizes, launches notification to mobile, does everything right and back to the screen to start a new process.

The second time it is done, is recorded in the mobile database, but does not synchronize, it seems that the service simply does not run.

When I close the system, I clean it from memory, then synchronization is done. I have done several tests and so far I could not solve.

Follows the codes:

public void finalizaCheckList(){
    ContentValues ctvResposta = new ContentValues();
    ctvResposta.put("status",1);
    SQLiteDatabase dbResposta = openOrCreateDatabase("respostas.db", Context.MODE_PRIVATE, null);
    long iCodigoResposta = dbResposta.insert("respostas","_id",ctvResposta);
    dbResposta.close();


    for (int i = 0; i < alR.size(); i++){
        RadioGroup rgResposta = alR.get(i);
        int handleItemSelecionado = rgResposta.getId();
        int itenSelecionado =   rgResposta.indexOfChild(findViewById(rgResposta.getCheckedRadioButtonId()));

        ContentValues ctv = new ContentValues();
        ctv.put("placa",placa);
        ctv.put("placanumero",_placanumero);
        ctv.put("handle_checklist",handle_checklist);
        ctv.put("tipopergunta",1);
        ctv.put("handle_checklist_pergunta",handleItemSelecionado);
        if (itenSelecionado == 0){
            ctv.put("resposta","S");
        } else {
            ctv.put("resposta","N");
        }
        ctv.put("usuario",handle_usuario);
        ctv.put("sincronizado",1);
        ctv.put("codigo_resposta",iCodigoResposta);

        SQLiteDatabase db1 = openOrCreateDatabase("checklist_resposta.db", Context.MODE_PRIVATE, null);
        db1.insert("checklist_resposta","_id",ctv);
        db1.close();
    }


    for (int ii = 0; ii < alE.size(); ii++){
        EditText edResposta = alE.get(ii);

        int handleItemSelecionado = edResposta.getId();
        String resposta = edResposta.getText().toString();

        ContentValues ctv = new ContentValues();
        ctv.put("placa",placa);
        ctv.put("placanumero",_placanumero);
        ctv.put("handle_checklist",handle_checklist);
        ctv.put("tipopergunta",2);
        ctv.put("handle_checklist_pergunta",handleItemSelecionado);
        ctv.put("resposta",resposta);
        ctv.put("usuario",handle_usuario);
        ctv.put("sincronizado",1);
        ctv.put("codigo_resposta",iCodigoResposta);

        SQLiteDatabase db1 = openOrCreateDatabase("checklist_resposta.db", Context.MODE_PRIVATE, null);
        db1.insert("checklist_resposta","_id",ctv);
        db1.close();
    }

    Intent intent = new Intent("br.cooper.system.checklist.ReplicarCheckLists") ;
    this.startService(intent) ;
}

Filing cabinet AndroidManifest.xml:

<service android:name="br.cooper.system.checklist.ReplicarCheckLists"
        android:enabled="true"
        android:process=":remote">
        <intent-filter >
            <action android:name="br.cooper.system.checklist.ReplicarCheckLists"/>
        </intent-filter>
    </service>

My code of replication:

public class ReplicarCheckLists extends Service implements Runnable {
private Handler mainHandler;
private Handler handler;
private String sXML = "";

@Override
public void onCreate(){
    if (verificaConexao()){
        new Thread(ReplicarCheckLists.this).start();
    }
}

@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onStart(Intent intent, int startId) {
    super.onStart(intent, startId);
}
@Override
public void onDestroy() {
    super.onDestroy();
}

@Override
public void run() {
    Looper.prepare();
    handler = new Handler();

    boolean post = handler.post(new Runnable() {
        @Override
        public void run() {
            //Criado para ser gerado quando for disparado a Thread
            SQLiteDatabase sqlRespostas = openOrCreateDatabase("respostas.db",Context.MODE_PRIVATE, null);
            Cursor cursorResposta = sqlRespostas.rawQuery("select _id from respostas where status = 1",null);

            SQLiteDatabase sqlSincronizado = openOrCreateDatabase("checklist_resposta.db", Context.MODE_PRIVATE, null);
            Cursor cursorR = sqlSincronizado.rawQuery("select placanumero from checklist_resposta group by placanumero", null);

            try {
                SQLiteDatabase sql = openOrCreateDatabase("checklist_resposta.db", Context.MODE_PRIVATE, null);
                Cursor cursor = null;
                Cursor cursorAtualizacao = sql.rawQuery("select _id, handle_checklist, placa, handle_checklist_pergunta, tipopergunta, usuario, resposta, placanumero, handle_checklist  from checklist_resposta where sincronizado = 1", null);

                SincronizaRespostas sincrona = new SincronizaRespostas();
                String sResposta = "";

                boolean bCabacalho = false;
                while (cursorResposta.moveToNext()){
                    cursor = sql.rawQuery("select _id, handle_checklist, placa, handle_checklist_pergunta, tipopergunta, usuario, resposta, placanumero, handle_checklist  " +
                            "from checklist_resposta where sincronizado = 1 " +
                            "and codigo_resposta =  " + cursorResposta.getString(cursorResposta.getColumnIndex("_id")) , null);
                    while (cursor.moveToNext()) {
                        if (!bCabacalho) {
                            geraXML("respostachecklist", "", false);
                            geraXML("placa", cursor.getString(cursor.getColumnIndex("placa")), false);
                            geraXML("checklist", cursor.getString(cursor.getColumnIndex("handle_checklist")), false);
                            geraXML("usuario", cursor.getString(cursor.getColumnIndex("usuario")), false);

                            bCabacalho = true;
                        }

                        geraXML("respostas","",false);
                        geraXML("pergunta", cursor.getString(cursor.getColumnIndex("handle_checklist_pergunta")), false);
                        geraXML("tipopergunta",cursor.getString(cursor.getColumnIndex("tipopergunta")),false);
                        geraXML("resposta",cursor.getString(cursor.getColumnIndex("resposta")),false);
                        geraXML("respostas", "", true);
                    }
                    geraXML("respostachecklist","",true);



                    if (sincrona.sincoriza(sXML).equals("OK")) {
                        gravaItemOk(cursorResposta.getInt(cursorResposta.getColumnIndex("_id")));
                    }
                    cursor.close();

                }

                sqlSincronizado.close();
                cursor.close();
                cursorAtualizacao.close();
                cursorR.close();
                sql.close();

            } catch (Exception ex) {
                notificacao(cursorR.getString(cursorR.getColumnIndex("placanumero")), true);
                Log.d("DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD", ex.getMessage());
            }


        }
    });
    Looper.loop();
    stopSelf();


}

I don’t know if I could make myself understood, but the problem seems to be simple, but I haven’t found the solution yet. I don’t know if anyone has been through this!!


Updating

I ran a test using the AsyncTask. The code went like this:

public class ReplicarCheckLists extends Service {
private Handler mainHandler;
private Handler handler;
private String sXML = "";


@Override
public void onCreate(){
    super.onCreate();
    // Migra a lógica de sincronização para o handleCommand
}

@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onStart(Intent intent, int startId) {
    super.onStart(intent, startId);
    handleCommand();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    handleCommand();
    return super.onStartCommand(intent, flags, startId);
}

public void handleCommand() {
    // Inicia uma nova AsyncTask para realizar as operações fora da Main Thread
    new AsyncTask<Void, Void, Void>() {
        @Override
        protected Void doInBackground(Void... params) {
            //Criado para ser gerado quando for disparado a Thread
            SQLiteDatabase sqlRespostas = openOrCreateDatabase("respostas.db",Context.MODE_PRIVATE, null);
            Cursor cursorResposta = sqlRespostas.rawQuery("select _id, placa from respostas where status = 1",null);

            String sPlacaNumero = "";

            try {
                SQLiteDatabase sql = openOrCreateDatabase("checklist_resposta.db", Context.MODE_PRIVATE, null);
                Cursor cursor = null;

                SincronizaRespostas sincrona = new SincronizaRespostas();


                boolean bCabacalho = false;
                while (cursorResposta.moveToNext()){
                    sPlacaNumero = cursorResposta.getString(cursorResposta.getColumnIndex("placa"));
                    cursor = sql.rawQuery("select _id, handle_checklist, placa, handle_checklist_pergunta, tipopergunta, usuario, resposta, placanumero, handle_checklist  " +
                            "from checklist_resposta where sincronizado = 1 " +
                            "and codigo_resposta =  " + cursorResposta.getString(cursorResposta.getColumnIndex("_id")) , null);


                    while (cursor.moveToNext()) {
                        if (!bCabacalho) {
                            geraXML("respostachecklist", "", false);
                            geraXML("placa", cursor.getString(cursor.getColumnIndex("placa")), false);
                            geraXML("checklist", cursor.getString(cursor.getColumnIndex("handle_checklist")), false);
                            geraXML("usuario", cursor.getString(cursor.getColumnIndex("usuario")), false);

                            bCabacalho = true;
                        }

                        geraXML("respostas","",false);
                        geraXML("pergunta", cursor.getString(cursor.getColumnIndex("handle_checklist_pergunta")), false);
                        geraXML("tipopergunta",cursor.getString(cursor.getColumnIndex("tipopergunta")),false);
                        geraXML("resposta",cursor.getString(cursor.getColumnIndex("resposta")),false);
                        geraXML("respostas", "", true);
                    }

                    geraXML("respostachecklist","",true);

                    if (sincrona.sincoriza(sXML).equals("OK")) {
                        gravaItemOk(cursorResposta.getInt(cursorResposta.getColumnIndex("_id")));
                        notificacao(sPlacaNumero, false);
                    } else {
                        notificacao(sPlacaNumero, true);
                    }

                }


                cursorResposta.close();
                sql.close();
            } catch (Exception ex) {
                Log.d("DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD", ex.getMessage());
            }
            return null;
        }
    }.execute();
}

@Override
public void onDestroy() {
    super.onDestroy();
}

But the following error occurs:

22856-23026/br.cooper.system.Checklist:remote D/DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD println needs a message

I don’t know what it could be, because this mistake is one try-catch.

And continue syncing after closing the app by full.

Anything else I might be doing to solve this problem?

  • Yes, this behavior is correct. I will check a point that I am not sure yet and prepare an answer.

  • Exchange the Log.d by a e.printStackTrace to see more details about the problem.

3 answers

2

I wondered what could be the mistake and by the way it was made, although not recommended, it works (in theory).

Looking at his code, he should recreate the Service (calling for onCreate) every time I called startService, I have no idea why exactly. My hypothesis is that it should be reusing the same instance and so does not call the onCreate even calling stopSelf().

If I may, I suggest a Refactoring in your code.

Instead of using the onCreate to make your sync logic, use the onStartCommand (is recommended in versions higher than SDK 5) to make its logic.

Also, as this using Threads, has even looked AsyncTask? It is a layer that facilitates the manipulation of Threads and UI update. I know there’s no UI involved, but here’s the tip.

Another modification would be to stop implementing the interface Runnable and using a AsyncTask anonymous, even if you don’t have UI, to facilitate code.

It would look something like:

public class ReplicarCheckLists extends Service {
    private Handler mainHandler;
    private Handler handler;
    private String sXML = "";

    @Override
    public void onCreate(){
        super.onCreate();
        // Migra a lógica de sincronização para o handleCommand
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        handleCommand();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        handleCommand();
        return super.onStartCommand(intent, flags, startId);
    }

    public void handleCommand() {
        // Inicia uma nova AsyncTask para realizar as operações fora da Main Thread

        new AsyncTask<Void, Void, Void>() {
            @Override
            protected void doInBackground(Void... params) {
                //Criado para ser gerado quando for disparado a Thread
                SQLiteDatabase sqlRespostas = openOrCreateDatabase("respostas.db",Context.MODE_PRIVATE, null);
                Cursor cursorResposta = sqlRespostas.rawQuery("select _id from respostas where status = 1",null);

                SQLiteDatabase sqlSincronizado = openOrCreateDatabase("checklist_resposta.db", Context.MODE_PRIVATE, null);
                Cursor cursorR = sqlSincronizado.rawQuery("select placanumero from checklist_resposta group by placanumero", null);

                try {
                    SQLiteDatabase sql = openOrCreateDatabase("checklist_resposta.db", Context.MODE_PRIVATE, null);
                    Cursor cursor = null;
                    Cursor cursorAtualizacao = sql.rawQuery("select _id, handle_checklist, placa, handle_checklist_pergunta, tipopergunta, usuario, resposta, placanumero, handle_checklist  from checklist_resposta where sincronizado = 1", null);

                    SincronizaRespostas sincrona = new SincronizaRespostas();
                    String sResposta = "";

                    boolean bCabacalho = false;
                    while (cursorResposta.moveToNext()){
                        cursor = sql.rawQuery("select _id, handle_checklist, placa, handle_checklist_pergunta, tipopergunta, usuario, resposta, placanumero, handle_checklist  " +
                                              "from checklist_resposta where sincronizado = 1 " +
                                              "and codigo_resposta =  " + cursorResposta.getString(cursorResposta.getColumnIndex("_id")) , null);

                        while (cursor.moveToNext()) {
                            if (!bCabacalho) {
                                geraXML("respostachecklist", "", false);
                                geraXML("placa", cursor.getString(cursor.getColumnIndex("placa")), false);
                                geraXML("checklist", cursor.getString(cursor.getColumnIndex("handle_checklist")), false);
                                geraXML("usuario", cursor.getString(cursor.getColumnIndex("usuario")), false);

                                bCabacalho = true;
                            }

                            geraXML("respostas","",false);
                            geraXML("pergunta", cursor.getString(cursor.getColumnIndex("handle_checklist_pergunta")), false);
                            geraXML("tipopergunta",cursor.getString(cursor.getColumnIndex("tipopergunta")),false);
                            geraXML("resposta",cursor.getString(cursor.getColumnIndex("resposta")),false);
                            geraXML("respostas", "", true);
                        }

                        geraXML("respostachecklist","",true);

                        if (sincrona.sincoriza(sXML).equals("OK")) {
                            gravaItemOk(cursorResposta.getInt(cursorResposta.getColumnIndex("_id")));
                        }

                        cursor.close();
                    }

                    sqlSincronizado.close();
                    cursor.close();
                    cursorAtualizacao.close();
                    cursorR.close();
                    sql.close();
                } catch (Exception ex) {
                    notificacao(cursorR.getString(cursorR.getColumnIndex("placanumero")), true);
                    Log.d("DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD", ex.getMessage());
                }
            }
        }.execute();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}
  • Wakim, !!

1


After so much forcing a successful attempt, I think I figured out what it might be, actually an alternative that I don’t know if it’s the right one, but apparently it worked, I simply pulled the plug:

Intent intent = new Intent("br.cooper.system.checklist.ReplicarCheckLists") ;
    stopService(intent) ;

In case you have a problem that someone has already been using in this way!??!

Thank you

0

Put this implementation into your service:

@Override
public int onStartCommand(Intent intent, int flags, int startId) 
{


   // Este flag faz com que o sistema restart o serviço caso seja parado, tanto pelo
   //usuário como pelo sistema. Só o aplicativo poderá pará-lo
    return START_STICKY;

}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.