我遇到了 Activity + Service
的问题,因为我有以下数量的活动和服务。
LoginActivity => OrderListActivity => AddOrderActivity => ConfirmOrderActivity
在某个间隔的持续时间内,来自另一个独立服务的服务呼叫以上。
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...");
}
}
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...");
}
}
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();
根据在数据库中插入记录的流程,一切正常。
当我从 ConfirmOrderActivity 成功下订单时,显示成功消息<{1}} 可取消 {{1} }。当我停止此活动的应用时,会自动同时调用AlertDialog
和false
。
我之后只调用来自
CheckAutoSyncReceivingOrder
的服务 在给定间隔后会自动调用但是出现问题 当我在显示对话框时销毁 ConfirmOrderActivity 时。
我不知道为什么它会在我直接停止活动时自动运行。
CheckAutoSyncSendingOrder
中使用LoginActivity
尝试了onStartCommand()
但没有效果。 (因为 START_NON_STICKY
是默认值。)Service
有没有解决方案?
答案 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()
意图,请启动服务。
有两种方法可以解决您的问题。
将您的两项服务设为foreground service。
您应该使用AlarmManager
来安排任务,而不是使用CheckAutoSyncReceivingOrder
和CheckAutoSyncSendingOrder
来安排其他服务的启动。
答案 3 :(得分:1)
如果运行您服务的进程被终止,Android系统将自动重启它,这是默认行为。
此行为由Service实现中onStartCommand()
的返回值定义。常量START_NOT_STICKY
告诉Android如果该进程被“杀死”,则不会重新启动该服务。
您需要在服务类中覆盖方法onStartCommand()
,并将所有代码从onStart()
方法移至onStartCommand()
方法。
根据Android文档:
每次重新启动服务时都会调用{p>对于已启动的服务,还有两种主要模式 根据他们的价值,他们可以决定参加比赛 从
onStartCommand()
返回:START_STICKY
用于提供服务 根据需要明确启动和停止,START_NOT_STICKY
或START_REDELIVER_INTENT
仅用于服务 在处理发送给他们的任何命令时保持运行
onStart()
方法,但如果返回onStartCommand()
,则不会调用START_NON_STICKY
方法。
不要再使用onStart(),不推荐使用它。
我希望它可以帮到你。