Symbian
Symbian OS Library

FAQ-0499 How can I launch an application and wait until it's finished to do something?

[Index][spacer] [Previous] [Next]



 

Classification: C++ Category: Threads & Processes
Created: 06/23/2000 Modified: 01/16/2002
Number: FAQ-0499
Platform: ER5, Symbian OS v6.0, Symbian OS v6.1

Question:
How can I launch an application and wait until it's finished to do something?

Answer:
This can be done via a simple Active Object. Consider this class:

//
// CThreadLogon
//
class CEikBusyMsgWin;
class CExampleAppUi;
class CThreadLogon : public CActive
    {public:
      CThreadLogon(CExampleAppUi& aAppUi);
      ~CThreadLogon();
      void ConstructL();
      void Request(const TThreadId& aId);private:
        void DoCancel();
        void RunL();private:
          RThread iThread;
          CExampleAppUi& iAppUi;
          CEikBusyMsgWin* iBusyMsg;
          HBufC* iBusyText;
          };
          CThreadLogon::CThreadLogon(CExampleAppUi& aAppUi)
            : CActive(EActivePriorityIpcEventsHigh), iAppUi(aAppUi)
            {
            }
            CThreadLogon::~CThreadLogon()
              {
              Cancel();
              delete iBusyMsg;
              User::Free(iBusyText);
              }
              void CThreadLogon::ConstructL()
                {
                CEikonEnv* eikonEnv=CEikonEnv::Static();
                iBusyMsg=new(ELeave) CEikBusyMsgWin(*eikonEnv);
                iBusyMsg->ConstructL(eikonEnv->RootWin());
                iBusyText=eikonEnv->AllocReadResourceL(R_EXAMPLE_WAITING_FOR_APP);
                CActiveScheduler::Add(this);
                }
                void CThreadLogon::DoCancel()
                  {
                  iBusyMsg->CancelDisplay();
                  iThread.LogonCancel(iStatus);
                  iThread.Close();
                  }
                  void CThreadLogon::RunL()
                    {
                    iBusyMsg->CancelDisplay();
                    iThread.Close();
                    iAppUi.LogonCallBackL();
                    }
                    void CThreadLogon::Request(const TThreadId& aId)
                      {
                      TInt err=iThread.Open(aId);
                      if (err)
                        {
                        TRequestStatus* pS=&iStatus;
                        User::RequestComplete(pS,err);
                        }else
                          iThread.Logon(iStatus);SetActive();
                          iBusyMsg->StartDisplay(iBusyText->Des(),EHRightVBottom);
                          }
                          All you now need to to is add a CThreadLogon* iThreadLogon member to your AppUi, do:
                            iThreadLogon=new(ELeave) CThreadLogon(*this);
                            iThreadLogon->ConstructL();
                            in the AppUi's constructor and finally construct a callback procedure in your AppUI. For example, this will bring your application to the foreground and show a simple message:

                            void CExampleAppUi::LogonCallBackL()
                              {
                              iEikonEnv->SetBusy(EFalse);

                              RWsSession& ws   = iEikonEnv->WsSession();
                              RWindowGroup& rw = iEikonEnv->RootWin();
                              TInt winId       = rw.Identifier();
                              TApaTask tApatsk(ws);
                              tApatsk.SetWgId(winId);
                              tApatsk.BringToForeground();

                              iEikonEnv->InfoWinL(R_EXAMPLE_APP_FINISHED);
                              }
                              When launching the app initially, you need to ensure the thread id is passed to the iThreadLogon AO. This could be done as follows:
                                iThreadLogon->Request(EikDll::StartAppL(*cmdLine));
                                iEikonEnv->SetBusy(ETrue);