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