Android:通过通知重新启动活动时保留HttpClient和AsyncTask
我有一个Android应用程序,它使用HttpClient将文件上传到我的Web服务。该应用程序有一个在上传文件时更新的通知,允许用户最小化应用程序并在后台执行其他操作。当我点击通知并重新启动活动时出现问题。My HttpClient连接包含到Web服务器的带有会话信息的Cookie,当通过录制通知重新启动活动时,此连接将丢失。似乎在重新启动时,进行上传的旧片段被销毁了(我知道这一点,因为我看到在重新启动时asynctask会优雅地停止)。我曾尝试使用保留的片段,但当应用程序重新启动时,它无法定位片段,尽管我将片段设置为保留 因此,我的问题是,如何重新启动一个活动并同时保留HttpClient连接和AsyncTask(在重新启动期间仍在进行上载的情况下,我需要这样做)Android:通过通知重新启动活动时保留HttpClient和AsyncTask,android,android-notifications,androidhttpclient,Android,Android Notifications,Androidhttpclient,我有一个Android应用程序,它使用HttpClient将文件上传到我的Web服务。该应用程序有一个在上传文件时更新的通知,允许用户最小化应用程序并在后台执行其他操作。当我点击通知并重新启动活动时出现问题。My HttpClient连接包含到Web服务器的带有会话信息的Cookie,当通过录制通知重新启动活动时,此连接将丢失。似乎在重新启动时,进行上传的旧片段被销毁了(我知道这一点,因为我看到在重新启动时asynctask会优雅地停止)。我曾尝试使用保留的片段,但当应用程序重新启动时,它无法定
生成通知(根据建议) RetainFragment代码(UploadTask扩展AsyncTask,CasRestProxyClient扩展HttpClient) 上传者活动(减少到我认为相关的内容)
在这种情况下,我可能会在
AsyncTask
上使用IntentService
。关于如何设置的基本知识可以在android文档中找到。使用IntentService
的好处是,一旦启动它的活动
(或者在您的情况下是片段
)被销毁,它就可以继续运行。您可以使用意图在您的活动
或片段
和意图服务
之间进行通信,以便通知意图服务
的其他组件
从AsyncTask
模型设置/转换非常简单。指向文档的链接将向您展示如何启动/停止服务。除此之外,由于服务在后台运行,因此无论您在AsyncTask
的后台中拥有什么,都可以在服务实现中有意义的地方使用。只需在您想要接收更新的组件中使用广播接收器
更新-服务与意向服务
android中有两种服务。一个正常的服务
,它保持在后台,独立于活动
,但在主线程上运行;一个IntentService
,它也保持在后台,但在单独的工作线程上运行。您可以在提供的链接中找到使用独立线程的多种不同方法
为了澄清上述问题,我将使用IntentService
,因为它能够从主线程运行。这在执行I/O操作时是至关重要的,自API 3.0以来就一直需要这样做IntentService
还允许更新回主线程,如使用Intent
所述。为了进一步比较这两种类型的服务
,我最终通过使用实现Messenger
接口的BoundService
实现了我想要的功能()。在应用程序关闭时,仅此一步仍然会导致服务自我毁灭。防止服务破坏并允许重新连接的关键是在调用bindService()
之前调用startService()
。这将使服务在后台运行,直到我的应用程序调用stopService()
(在我的情况下,当用户明确注销时)
在UploaderActivity.onStart()方法中调用:
请澄清回答中使用的是IntentService
而不是Service
。这有助于防止任务关闭。我看不到将httpclient传递给服务的方法(尽管序列化可能会有所帮助)、从服务返回客户端(当应用程序重新启动时,它将需要这样做)以及终止任务的能力(如果调用了取消或注销操作)。可以在服务中执行这些操作吗?可以-我不会将HttpClient
传递给服务。相反,只需传递您将要上传的数据(或URI,如果存储在本地),然后初始化您的HttpClient
、HttpPost
或您需要的服务中的任何元素。因为服务有自己的上下文,很像一个活动,只是没有任何UI功能。
Builder builder = new NotificationCompat.Builder( getActivity() );
builder.setSmallIcon( R.drawable.ic_stat_notify_upload );
builder.setContentTitle( "Uploads" );
builder.setContentText( "Uploading " + fileCount + " file(s)" );
builder.setProgress( fileCount, 0, false );
Intent notificationActionIntent = new Intent( getActivity(), UploaderActivity.class );
TaskStackBuilder stackBuilder = TaskStackBuilder.create( getActivity() );
stackBuilder.addParentStack( UploaderActivity.class );
stackBuilder.addNextIntent( notificationActionIntent );
PendingIntent notificationPendingIntent = stackBuilder.getPendingIntent( 0, PendingIntent.FLAG_UPDATE_CURRENT );
builder.setContentIntent( notificationPendingIntent );
public class RetainFragment extends Fragment {
private CasRestProxyClient casClient;
private UploadEftTask uploadTask;
@Override
public void onCreate ( Bundle savedInstanceState ) {
super.onCreate( savedInstanceState );
setRetainInstance( true );
}
public ICasRestProxyClient getCasClient() {
return casClient;
}
public void setCasClient(ICasRestProxyClient casClient) {
this.casClient = casClient;
}
public UploadEftTask getUploadTask() {
return uploadTask;
}
public void setUploadTask(UploadEftTask uploadTask) {
this.uploadTask = uploadTask;
}
}
public class UploaderActivity extends Activity {
private static final String RetainFragmentIdString = "RETAIN_FRAGMENT";
private RetainFragment retainFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LoggerConfigurator.configure();
setContentView(R.layout.activity_uploader);
FragmentManager fragMgr = getFragmentManager();
Fragment dataFragment = fragMgr.findFragmentByTag( RetainFragmentIdString );
if ( dataFragment != null && dataFragment instanceof RetainFragment ) {
retainFragment = (RetainFragment)dataFragment;
// Restore state here...
} else {
retainFragment = new RetainFragment();
FragmentTransaction fragTrans = fragMgr.beginTransaction();
fragTrans.add( retainFragment, RetainFragmentIdString );
fragTrans.commit();
// Show initial state here...
}
}
@Override
public void onDestroy ( ) {
retainFragment.setCasClient( uploadFragment.getCasClient() );
retainFragment.setUploadTask( uploadFragment.getUploadTask() );
super.onDestroy();
}
}
Intent initService = new Intent( this, UploaderService.class );
startService( initService );
// serviceConnection is a member of UploaderActivity of type
// android.content.ServiceConnection that handles when the service binds.
// This needs to be a class member to unbind() when the activity is destroyed
bindService( initService, serviceConnection, Context.BIND_AUTO_CREATE );