服务自动调用销毁活动

时间:2015-12-30 12:25:51

标签: android android-activity android-service android-intentservice

我遇到了 Activity + Service 的问题,因为我有以下数量的活动和服务。

活动:

  

LoginActivity => OrderListActivity => AddOrderActivity => ConfirmOrderActivity

服务:

  1. ReceivingOrderService - 从服务器接收新数据
  2. SendingOrderService - 将新数据发送到服务器
  3. 在某个间隔的持续时间内,来自另一个独立服务的服务呼叫以上。

    1. CheckAutoSyncReceivingOrder - 调用ReceivingOrderService(间隔15分钟)
    2. CheckAutoSyncSendingOrder - 调用SendingOrderService(Interval 3Mins)
    3. 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#Final Task,我已经要求插入数据:

      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();
      

      根据在数据库中插入记录的流程,一切正常。

      添加查询后:

      enter image description here

      销毁活动并获取以下Logcat:

      enter image description here

      主要问题:

      当我从 ConfirmOrderActivity 成功下订单时,显示成功消息<{1}} 可取消 {{1} }。当我停止此活动的应用时,会自动同时调用AlertDialogfalse

      编辑:

        

      我之后只调用来自CheckAutoSyncReceivingOrder的服务   在给定间隔后会自动调用但是出现问题   当我在显示对话框时销毁 ConfirmOrderActivity 时。

      我不知道为什么它会在我直接停止活动时自动运行。

      我在CheckAutoSyncSendingOrder中使用LoginActivity尝试了onStartCommand()但没有效果。 (因为 START_NON_STICKY 是默认值。)

      Service

      有没有解决方案?

4 个答案:

答案 0 :(得分:4)

您需要运行service in the foreground,以便在活动被销毁时,服务或使用绑定服务并使用活动生命周期管理绑定,因此在销毁活动时不会不断重新启动。

从这个Android文档教程Bound Services

您需要为每项服务执行此操作。

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;
        }
    };
}   

管理service lifecycle。使用计时器重新启动相同的服务,不要创建新服务。

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

答案 1 :(得分:1)

(1)对话:

解决方案是在退出dismiss()之前致电您Dialog上的Activity,例如在onDestroy()。所有 Windows&amp;在离开Activity之前应该关闭对话

(2)对于您的服务自动启动:

你必须查看服务从onStartCommand方法返回的值。默认值为START_STICKY,它将在销毁后重新启动服务。请查看onStartCommand documentation了解更多详情:

答案 2 :(得分:1)

应用程序被杀后服务被杀死(添加服务onStartCommand()onDestroy()功能的日志并尝试从最近的列表中清除应用程序,您将看到onDestroy()被调用.Android将重新启动如果您在START_STICKY中返回onStartCommand()意图,请启动服务。

有两种方法可以解决您的问题。

  1. 将您的两项服务设为foreground service

  2. 您应该使用AlarmManager来安排任务,而不是使用CheckAutoSyncReceivingOrderCheckAutoSyncSendingOrder来安排其他服务的启动。

答案 3 :(得分:1)

如果运行您服务的进程被终止,Android系统将自动重启它,这是默认行为。

此行为由Service实现中onStartCommand()的返回值定义。常量START_NOT_STICKY告诉Android如果该进程被“杀死”,则不会重新启动该服务。

您需要在服务类中覆盖方法onStartCommand(),并将所有代码从onStart()方法移至onStartCommand()方法。

根据Android文档:

  

对于已启动的服务,还有两种主要模式   根据他们的价值,他们可以决定参加比赛   从onStartCommand()返回:START_STICKY用于提供服务   根据需要明确启动和停止,START_NOT_STICKY   或START_REDELIVER_INTENT仅用于服务   在处理发送给他们的任何命令时保持运行

每次重新启动服务时都会调用{p> onStart()方法,但如果返回onStartCommand(),则不会调用START_NON_STICKY方法。

不要再使用onStart(),不推荐使用它。

我希望它可以帮到你。