Help on Telephony application
| Sat, 2005-12-24 12:31 | |
|
Hello,
Well I have been working on a telephony application which essentially deals with invoking the application when a phone call is recd. by a mobile device Initially the application that I was studying gets activated (comes to foreground) when a call is recd. by the device & straightaway starts answering the call What I want to do is when a call is recd. the application shld come to foregrnd which it does & ask the user whether he wants to accept or reject the incoming call which I am trying to acheive but somehow I can't. Can anybody help me out by providing a small code snippet if not the entire code to do the above mentioned task ?? Thanks, Yogesh Khanolkar |
|






Forum posts: 12
I am trying to do the same thing. The point here is
to completely disable the default call handler of
the phone. I haven't found yet how to do it.
I will try to search / investigate.
Can anybody help?
Panayotis
panayotis
Forum posts: 34
Well just need to know if any particular function can be used to notify an incoming call & take action whether to accept/reject the call
Here I have been playing with NotifyIncomingCall() of RCall class & then passing the status as EStatusRinging to the application so that the user can Accept/Reject the call
But somehow cant get it
Can anybody guide me out of this
Thanks,
Yogesh Khanolkar
Forum posts: 12
NotifyIncomingCall() is the correct method to use
in order to be notified for the incoming call (at least
the one I use myself). The whole logic should be
encoded inside your CActive object, RunL() and
StartL() methods. I suppose that you StartL()
method sends the NotifyIncomingCall() request and
the RunL() method waits for the completion of the
request. Use a simple state machine on your
CActive object to make sure that when the RunL()
method is called by the framework, objeck knows
what to do.
This is in general what it has to be done.
You are saying that "but somehow cant get it".
What exactly do you get and what you don't?
Can you be more specific? Do you want to post your
CActive object code in order for us to check that you
have it done correctly?
Panayotis
panayotis
Forum posts: 34
Oh yes let me be more specific on what I am doing exactly
First let me tell u how it was earlier, this is for the CallReceiver class where the asynchronous process is happening
I will just concentrate on StartL() & RunL() methods
//StartL() starts here---
void CCallReceiver::StartL()
    {
    switch(iState)
        {
        case EWaiting:
            // sets iCallName when it receives an incoming call
            iLine.NotifyIncomingCall(iStatus, iCallName);
            callreclog.Write(_L("StartL - EWaiting"));
            break;
        case EAnswering:
            User::LeaveIfError(iCall.OpenExistingCall(iLine, iCallName));
            iCall.AnswerIncomingCall(iStatus);
            callreclog.Write(_L("StartL - EAnswering"));
            break;
        case EWatching:
            callreclog.Write(_L("StartL - EWatching"));
            iCall.NotifyStatusChange(iStatus, iCallStatus);
            break;
        }
    SetActive();
    }
//RunL() starts here-----
void CCallReceiver::RunL()
    {
    if(iStatus.Int() != KErrNone)
        return;
    switch(iState)
        {
        case EWaiting:
            {
            //answer the call
            iState = EAnswering;
            callreclog.Write(_L("RunL() EWaiting"));
            StartL();
            break;
            }
        case EAnswering:
            {
            iState = EWatching;
            callreclog.Write(_L("RunL() EAnswering"));
            StartL();
            callreclog.Write(_L("HandleCallInChangeL called"));
            iObserver.HandleCallInChangeL(RCall::EStatusConnected);
            callreclog.Write(_L("HandleCallInChangeL completed"));
            break;
            }
        case EWatching: // To check whether the caller has hung up or not
            {
            User::LeaveIfError(iCall.GetStatus(iCallStatus));
            callreclog.Write(_L("RunL() EWatching"));
            if (iCallStatus == RCall::EStatusHangingUp)
                {
                iObserver.HandleCallInChangeL(iCallStatus);
                iCall.Close();
                iState = EWaiting;
                }
            StartL();
            break;
            }
        }
    }
As seen above the class waits for the incoming call & straightaway starts answering the call... Now as I said earlier I want to let the user know that a call has been recd. before the call can be answered
So I made the following changes in the above code
//StartL() starts here-----
void CCallReceiver::StartL()
    {
    switch(iState)
        {
        case EWaiting:
            // sets iCallName when it receives an incoming call
            iLine.NotifyIncomingCall(iStatus, iCallName);
            callreclog.Write(_L("StartL - EWaiting"));
            break;
        case EAnswering:
            User::LeaveIfError(iCall.OpenExistingCall(iLine, iCallName));
            iCall.AnswerIncomingCall(iStatus);
            callreclog.Write(_L("StartL - EAnswering"));
            break;
        case EWatching:
            callreclog.Write(_L("StartL - EWatching"));
            iCall.NotifyStatusChange(iStatus, iCallStatus);
            break;
        }
    SetActive();
    }
//RunL() starts here-----
void CCallReceiver::RunL()
    {
    if(iStatus.Int() != KErrNone)
        return;
    switch(iState)
        {
        case EWaiting:
            {
            //notify the application, that a call is recd.  Â
            iObserver.HandleCallInChangeL(RCall::EStatusRinging);
            callreclog.Write(_L("RunL() EWaiting"));
            break;
            }
        case EAnswering:
            {
            iState = EWatching;
            callreclog.Write(_L("RunL() EAnswering"));
            StartL();
            callreclog.Write(_L("HandleCallInChangeL called"));
            iObserver.HandleCallInChangeL(RCall::EStatusConnected);
            callreclog.Write(_L("HandleCallInChangeL completed"));
            break;
            }
        case EWatching: // To check whether the caller has hung up or not
            {
            User::LeaveIfError(iCall.GetStatus(iCallStatus));
            callreclog.Write(_L("RunL() EWatching"));
            if (iCallStatus == RCall::EStatusHangingUp)
                {
                iObserver.HandleCallInChangeL(iCallStatus);
                iCall.Close();
                iState = EWaiting;
                }
            StartL();
            break;
            }
        }
    }
& After intimating the application about the call, I am letting the user to Accept / Reject the call & then complete the asynchronous process of Answering the call OR Ending the Call
But now as soon as the call comes in & the application doesnot come into foreground & the default phone window takes the call as usual
Kindly let me know if any changes r required in the above code
Thanks,
Yogesh Khanolkar
Forum posts: 12
In your last code segment, the most recent, one,
I initially have a problem with your RunL() method,
which does not seem to change the state of the
active object on the EWaiting. In other words,
I would expect to have a change in state.
Hence, I will assume that the line:
EAnswering or leaving it as it is EWaiting, depending
on user's reaction. Is that correct? Please confirm.
Now, if you want to bring your application on the
foreground, did you try to implement something
like the following (implementation of the
void C<your AppUi class>AppUi::HandleForegroundEventL( TBool aForeground ) {
// Call Base class method
CAknAppUi::HandleForegroundEventL( aForeground );
if ( !aForeground ) {
RWindowGroup * win;
win = & CCoeEnv::Static()->RootWin();
win->SetOrdinalPosition( 0, ECoeWinPriorityAlwaysAtFront );
} // if not in foreground
} // end of the method
This piece of code will force your application to be
on the foreground. However, it may be a good idea to check inside the method about the call state (to be in ringing mode) and not just write the method
as I have it above. If you leave it as above, then
user will not be able to use any of the other applications in the phone unless he/she closes your
application.
Let me know if the above helps.
Panayotis
panayotis
Forum posts: 34
Yes I havent provided any state in the RunL() function as the function
Simultaneously I am also changing the Command Button Array to Accept/Reject from the normal Options/Exit so that when the user selects the Accept key & only then I call a function from the CallReceiver Engine to accept the call
This function changes the state to EAnswering & then implements the following code as follows
User::LeaveIfError(iCall.OpenExistingCall(iLine, iCallName));
iCall.AnswerIncomingCall(iStatus);
This is how it should work but it doesnt
Also let me tell about the function that brings the application to foreground that I am implementing is as follows
TApaTask currentTask = taskList.FindByPos(0);
TApaTask ourAppTask = taskList.FindApp(KUidTestPhone);
if(currentTask.ThreadId() != ourAppTask.ThreadId())
      ourAppTask.BringToForeground();
Now this code worked earlier when I was answering the call without intimating the user about the call i.e I was bringing the application to foreground as soon as a call was received & answered according to the code provided in my earlier posts
But now after the changes I made the same code for bringing the application to foreground doesnot work
Also I tried using the code provided by u for bringing the app. to foreground but it doesnot work either
The function that you provided
CAknAppUi::HandleForegroundEventL( aForeground );
is for events happening when the application is in the foreground & not for bringing the application to foreground
Please comment on this 1, & let me know about this
Thanks,
Yogesh
Forum posts: 12
you are saying that:
CAknAppUi::HandleForegroundEventL( aForeground );
is for events happening when the application is in the foreground & not for bringing the application to foreground
I do not agree with you. This is the method that is
called by the Windoes Server framework to inform
notify an application that will be brought to
foreground or background (depending on the value
of "aForeground").
Hence, the expected behaviour of the code that I
gave you is the following: The default call handler
of your phone will NEVER come to foreground
(or any application) and always your application
will be on the foreground.
It works on my similar application. I do not
understand why it does not work on yours.
I am doing development using NOKIA 7610.
What is the phone you are using for your
development?
If you want to send me by e-mail (it is published)
all of your source code I could find out what is
going on and let you know. It's up to you.
BR
Panayotis
panayotis
Forum posts: 34
I am working on a telephony application which deals with incoming calls. I have a Phone Engine which deals with the basic connectivity with the RTelServer. I also have a CallReceiver class which is specifically meant for dealing with incoming calls
Whenever an incoming call comes in, the application comes into foreground & asks the user whether he wants to Accept/Reject the incoming call & upon selection accordingly accepts/rejects the call
But when I press the Accept button the call doesnot get answered
Following is the code that I am trying from the Call Receiver class
    {
    callreclog.Write(_L("### CCallReceiver::RunL() = 1 ###"));
    if(iStatus.Int() != KErrNone)
    {
       callreclog.Write(_L("### CCallReceiver::RunL() = 2 ###"));
       return;
    }
    switch(iState)
        {
        case EWaiting: // To intimate the application abyt the incoming call arrived
            callreclog.Write(_L("RunL() EWaiting"));
            iState = ERinging;
            StartL();
            callreclog.Write(_L("HandleCallInChangeL called"));
            iObserver.HandleCallInChangeL(RCall::EStatusRinging);
            callreclog.Write(_L("HandleCallInChangeL completed"));
            break;
        case ERinging: // To decide the status of the incoming call
            callreclog.Write(_L("RunL() ERinging"));
            if ( iCheckStatus == EAccept ) // Call accepted
            {
              callreclog.Write(_L("EAccept Apprvd."));
              iState = EAnswering;
              StartL();
              break;
            }
            if ( iCheckStatus == EReject ) // Call rejected
            {
              callreclog.Write(_L("EReject Apprvd."));
              iObserver.HandleCallInChangeL(RCall::EStatusHangingUp);
              iState = EWaiting;
              StartL();
              break;
            }
            User::LeaveIfError(iLine.GetStatus(iLineStatus));
            if (iLineStatus == RCall::EStatusHangingUp) // Call hungup by the caller
            {
              //Caller hung up before the call was accepted / rejected
              callreclog.Write(_L("Caller HungUp"));
              iObserver.HandleCallInChangeL(iLineStatus);
              iState = EWaiting;
              StartL();
              break;
            }
        case EAnswering: // To answer the accepted incoming call
            callreclog.Write(_L("RunL() EAnswering"));
            iState = EWatching;
            StartL();
            callreclog.Write(_L("HandleCallInChangeL called"));
            iObserver.HandleCallInChangeL(RCall::EStatusConnected);
            callreclog.Write(_L("HandleCallInChangeL completed"));
            break;
        case EWatching: // To check whether the caller has hung up or not
            User::LeaveIfError(iCall.GetStatus(iCallStatus));
            callreclog.Write(_L("RunL() EWatching"));
            if (iCallStatus == RCall::EStatusHangingUp)
                {
                iObserver.HandleCallInChangeL(iCallStatus);
                iCall.Close();
                iState = EWaiting;
                }
            StartL();
            break;
        } // End of switch
    }
void CCallReceiver::StartL()
    {
    switch(iState)
        {
        case EWaiting: // Sets iCallName when it receives an incoming call
            iLine.NotifyIncomingCall(iStatus, iCallName);
            callreclog.Write(_L("StartL - EWaiting"));
            break;
        case ERinging: // Notifies the change in status of iLine
            callreclog.Write(_L("StartL - ERinging"));
            iLine.NotifyStatusChange(iStatus, iLineStatus);
            break;
        case EAnswering: // Opens existing call & answers it
            callreclog.Write(_L("StartL - EAnswering"));
            User::LeaveIfError(iCall.OpenExistingCall(iLine, iCallName));
            callreclog.Write(_L("Opens Existing Call"));
            iCall.AnswerIncomingCall(iStatus);
            callreclog.Write(_L("Answers Incoming Call"));
            break;
        case EWatching: // Notifies the change in status of iCall
            callreclog.Write(_L("StartL - EWatching"));
            iCall.NotifyStatusChange(iStatus, iCallStatus);
            break;
        }
    SetActive();
    callreclog.Write(_L("SetActive called"));
    }
In the above code when it comes to Answering the Call (StartL() method for EAnswering) the SetActive gets called but when it enters the RunL() method the control returns from the line
    {
       callreclog.Write(_L("### CCallReceiver::RunL() = 2 ###"));
       return;
    }
Please help me out in this,
Thanks,
Yogesh