Подтвердить что ты не робот

Автоматический вызов службы уничтожения

Я столкнулся с проблемой Activity + Service, поскольку у меня есть следующее количество операций и служб.

Деятельность:

LoginActivity = > OrderListActivity = > AddOrderActivity = > ConfirmOrderActivity

Услуги:

  • ReceivingOrderService - получение новых данных с сервера
  • SendingOrderService - отправка новых данных на сервер

Выше обоих вызовов службы из другой отдельной службы в течение некоторого интервала .

  1. CheckAutoSyncReceivingOrder - вызов функции ReceivingOrderService (интервал 15 минут)
  2. CheckAutoSyncSendingOrder - вызов функции SendingOrderService (интервал 3Mins)

CheckAutoSyncReceivingOrder:

public class CheckAutoSyncReceivingOrder extends Service {

    Timer timer;

    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void onStart(Intent intent, int startId) {
        // TODO Auto-generated method stub

        if(timer != null) {
            timer.cancel();
            Log.i(TAG, "RECEIVING OLD TIMER CANCELLED>>>");
        }

        timer = new Timer();

        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                if(InternetConnection.checkConnection(getApplicationContext())) {
                    if(getDatabasePath(DatabaseHelper.DATABASE_NAME).exists())
                        startService(new Intent(CheckAutoSyncReceivingOrder.this, ReceivingOrderService.class));
                } else {
                    Log.d(TAG, "Connection not available");
                }
            }
        }, 0, 60000); // 1000*60*15 = 9,00,000 = 15 minutes
    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();

        if(timer != null)
            timer.cancel();

        Log.d(TAG, "Stopping Receiving...");
    }
}

CheckAutoSyncSendingOrder:

public class CheckAutoSyncSendingOrder extends Service {

    Timer timer;

    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void onStart(Intent intent, int startId) {
        // TODO Auto-generated method stub

        if(timer != null) {
            timer.cancel();
            Log.i(TAG, "OLD TIMER CANCELLED>>>");
        }

        timer = new Timer();

        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                Log.i(TAG, ">>>>>>>> SENDING AUTO SYNC SERVICE >>>>>>>>");
                if(InternetConnection.checkConnection(getApplicationContext())) {
                    if(getDatabasePath(DatabaseHelper.DATABASE_NAME).exists())
                        startService(new Intent(CheckAutoSyncSendingOrder.this, SendingOrderService.class));
                } else {
                    Log.d(TAG, "connection not available");
                }
            }
        }, 0, 120000); //  1000*120*15 = 1,800,000 = 15 minutes
    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();

        if(timer != null)
            timer.cancel();

        Log.d(TAG, "Stopping Sending...");
    }
}

ConfirmOrderActivity # Заключительная задача, которую я вызвал для ввода данных:

new AsyncTask<Void, Void, Integer>() {

    ProgressDialog progressDialog;

    @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub
        super.onPreExecute();

        progressDialog = new ProgressDialog(
                ConfirmOrderProductActivity.this);
        progressDialog.setMessage("Inserting "
                + (isInquiry ? "Inquiry" : "Order") + "...");
        progressDialog.setCancelable(false);
        progressDialog
                .setProgressStyle(ProgressDialog.STYLE_SPINNER);
        progressDialog.show();
    }

    @Override
    protected Integer doInBackground(Void... params) {
        // TODO Auto-generated method stub
        int account_id = context.getSharedPreferences(PREF_DATA,
                MODE_APPEND).getInt(DATA_ACCOUNT_ID, 0);

        /**
         * Check Whether isInquiry or not...
         */
        product_type = isWeight ? 1 : 0;
        if (isInquiry) {
            /*
             * INSERTING DATA IN INQUIRY TABLE
             */
            return m_inquiry_id;
        } else {
            /*
             * INSERTING DATA IN ORDER TABLE
             */
            return m_order_id;
        }
    }

    @Override
    protected void onPostExecute(Integer m_order_id) {
        // TODO Auto-generated method stub
        super.onPostExecute(m_order_id);

        progressDialog.dismiss();

        if (dbHelper.db.isOpen())
            dbHelper.close();

        String title = "Retry";
        String message = "There is some problem, Go Back and Try Again";

        AlertDialog.Builder alert = new AlertDialog.Builder(
                ConfirmOrderProductActivity.this);

        if (m_order_id != -1) {
            title = isInquiry ? "New Inquiry" : "New Order";
            message = isInquiry ? "Your Inquiry Send Successfully." : "Your Order Saved Successfully.";
            alert.setIcon(R.drawable.success).setCancelable(false);
        } else {
            alert.setIcon(R.drawable.fail).setCancelable(false);
        }

        alert.setTitle(title).setMessage(message)
                .setPositiveButton("OK", new OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog,
                            int which) {
                        // TODO Auto-generated method stub
                        dialog.dismiss();
                        startActivity(new Intent(
                                ConfirmOrderProductActivity.this,
                                FragmentChangeActivity.class)
                                .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));

                        /* Opening Left to Right Animation */
                        overridePendingTransition(R.anim.right_out,
                                R.anim.right_in);
                    }
                });

        AlertDialog alertDialog = alert.create();
        alertDialog.show();

    }
}.execute();

Все работает отлично в соответствии с потоком вставки записей в базу данных.

После добавления запроса:

введите описание изображения здесь

Уничтожение активности и переход к следующему Logcat:

введите описание изображения здесь

Основная проблема:

Когда я успешно разместил заказ с ConfirmOrderActivity, он отображает AlertDialog сообщения Успешное, которое отменяется false. Когда я останавливаю приложение из этого действия, Его вызов как CheckAutoSyncReceivingOrder, так и CheckAutoSyncSendingOrder автоматически.

Отредактировано:

Я вызываю только сервис из LoginActivity, после чего он автоматически вызывается через заданные интервалы. Но возникает проблема когда я разрушаю ConfirmOrderActivity, когда отображается диалог.

Я не знал, почему это происходит, потому что он работает автоматически, когда я прекращаю действие напрямую.

Я пробовал onStartCommand() с START_NON_STICKY в Service, но не работал. (как START_STICKY по умолчанию.)

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

Есть ли какое-либо решение?

4b9b3361

Ответ 1

Вам нужно либо запустить службу на переднем плане, поэтому, когда действие будет уничтожено, будет ли служба или использовать связанный сервис и управлять привязка к жизненному циклу активности, поэтому он не перезапускается, когда активность уничтожается.

В этом учебнике по андроидным документам Связанные службы

Вам нужно сделать это для каждой службы.

public class CheckAutoSyncReceivingOrder extends Service {
    // Binder given to clients
    private final IBinder mBinder = new LocalBinder();

    public class LocalBinder extends Binder {
        CheckAutoSyncReceivingOrder getService() {
        return CheckAutoSyncReceivingOrder.this;
    }
}

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

Из вашей активности, которая создает и вызывает службу, что когда она уничтожена, вы хотите, чтобы ваш сервис был разрушен.

public class BindingActivity extends Activity {
    CheckAutoSyncReceivingOr mService;
    boolean mBound = false;


    @Override
    protected void onStart() {
        super.onStart();
        // Bind to CheckAutoSyncReceivingOr
        Intent intent = new Intent(this, CheckAutoSyncReceivingOr.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        // Unbind from the service
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }

    /** Defines callbacks for service binding, passed to bindService() */
    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className,
            IBinder service) {
            // We've bound to CheckAutoSyncReceivingOr, cast the IBinder and get CheckAutoSyncReceivingOr instance
            LocalBinder binder = (LocalBinder) service;
            mService = binder.getService();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };
}   

И управляйте жизненным циклом службы. Перезапустите ту же службу с помощью таймера, не создавайте новую службу.

public class ExampleService extends Service {
    int mStartMode;       // indicates how to behave if the service is killed
    IBinder mBinder;      // interface for clients that bind
    boolean mAllowRebind; // indicates whether onRebind should be used

    @Override
    public void onCreate() {
        // The service is being created
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // The service is starting, due to a call to startService()
        return mStartMode;
    }
    @Override
    public IBinder onBind(Intent intent) {
        // A client is binding to the service with bindService()
        return mBinder;
    }
    @Override
    public boolean onUnbind(Intent intent) {
        // All clients have unbound with unbindService()
        return mAllowRebind;
    }
    @Override
    public void onRebind(Intent intent) {
        // A client is binding to the service with bindService(),
        // after onUnbind() has already been called
    }
    @Override
    public void onDestroy() {
        // The service is no longer used and is being destroyed
    }
}

Примечание START_NOT_STICKY предотвратит перезапуск службы только в том случае, если устройство недостаточно памяти.

Помните, что вы, где вы запускаете службы, просто запускаете его один раз и разрешаете службе поддерживать собственный жизненный цикл, пока вы не уничтожите его своей деятельностью.

Это ответ на ваш первоначальный неотредактированный вопрос, когда приложение было таинственным сбоем:

Вам нужно уничтожить диалог перед контекстным окном, к которому привязан диалог. Это вызовет проблему. Таким образом, важно, чтобы поток программ и порядок закрытия и очистки ресурсов были важны. Они, как правило, должны быть уничтожены в обратном порядке, они были созданы, если они зависят от родительских окон (которые часто бывают в форме определенного вида деятельности).

Трудно проследить ваш код, так что это общий ответ.

Использовать onPause и onDestroy в своих действиях.

Во всех ваших действиях управляйте любыми ресурсами, которые вы создали в рамках этого действия, и с нулевой проверкой, закройте их. Как и у вас в вашем классе обслуживания. Если вы хотите переопределить родительский onDestroy, поместите свой код в super.onDestroy.

protected void onDestroy() {

    if(timer != null)
        timer.cancel();

    Log.d(TAG, "Stopping Sending...");

    super.onDestroy();
}

Ответ 2

(1) Для вашего диалога:

Решение состоит в вызове dismiss() в Dialog, созданном вами перед выходом из Activity, например. в onDestroy(). Все Windows и Dialog должны быть закрыты перед тем, как оставить Activity.

(2) Для автозагрузки службы

вам нужно посмотреть на значение, возвращаемое службой из метода onStartCommand. По умолчанию используется START_STICKY, который перезапустит службу после ее уничтожения. Взгляните на документацию onStartCommand для получения более подробной информации:

Ответ 3

Службы убиты, когда приложение было убито (добавьте функции журналов в службу onStartCommand() и onDestroy()) и попробуйте очистить приложение из недавнего списка, и вы увидите, что вызывается onDestroy(). Android снова запустит службу, если вы вернули START_STICKY цель onStartCommand()).

Существует два подхода к устранению проблемы.

  • Либо сделайте две службы в качестве переднего плана.

  • Вместо того, чтобы использовать CheckAutoSyncReceivingOrder и CheckAutoSyncSendingOrder для планирования запуска других служб, вы должны использовать AlarmManager для расписания ваша задача.

Ответ 4

Если процесс, запускающий вашу службу, будет убит, система Android автоматически перезапустит его по умолчанию.

Это поведение определяется возвращаемым значением onStartCommand() в вашей реализации службы. Константа START_NOT_STICKY сообщает Android не перезапускать службу, если она работает, пока процесс "убит".

Вам необходимо переопределить метод onStartCommand() в вашем классе обслуживания и переместить весь ваш код из метода onStart() в метод onStartCommand().

Согласно документации на Android:

Для начатых сервисов существуют два дополнительных основных режима которые они могут решить, в зависимости от значения, которое они return from onStartCommand(): START_STICKY используется для служб, которые явно запускаются и останавливаются по мере необходимости, а START_NOT_STICKYили START_REDELIVER_INTENT используются для служб, которые должны остаются включенными при обработке любых команд, отправленных им

onStart() вызывает вызовы каждый раз при перезапуске службы, но метод onStartCommand() не вызывается, если вы возвращаете START_NON_STICKY.

Не использовать onStart() больше, он устарел.

Надеюсь, это поможет вам.