I want to know whether the call is disconnected or continued, and based on that I want to perform an action in the application.
Can anyone tell me how to check if the phone call is disconnected or not?
along with that I also want to know if it is received by the end-user or not
any kind of help will be appreciated.
thank you
I think you should take the steps I list below:
One line of code can make a phone call
Wait for any in-flight phone
Calls Watch everything that happens on the phone during a single Call or all
calls.
Keep track of the length of calls, errors, and
call drops.
Now let’s start
Install the plugin
Flutter_phone_state: ^0.5.8
Initiate a call
It is best to make calls from your app whenever you can. This is the best way to find where the call came from.
final phoneCall = FlutterPhoneState.makePhoneCall("480-555-1234");
The truth about a call comes from a PhoneCall object.
showCallInfo(PhoneCall phoneCall) {
print(phoneCall.status);
print(phoneCall.isComplete);
print(phoneCall.events);
}
PhoneCall.events can be read as a stream, and when the call is over, the plugin will gracefully close the stream. The plugin keeps an eye on all calls in progress and will eventually force any call to time out.
watchEvents(PhoneCall phoneCall) {
phoneCall.eventStream.forEach((PhoneCallEvent event) {
print("Event $event");
});
print("Call is complete");
}
You could also just wait until the call is over.
waitForCompletion(PhoneCall phoneCall) async {
await phoneCall.done;
print("Call is completed");
}
Accessing in-flight calls
In-flight calls can be accessed like this:
final `activeCalls = FutterPhoneState.activeCalls;`
Note that activeCalls is a copy of the calls at the time you called it. This copy cannot be changed. It won't be updated on its own.
Watching all events
You can watch all the events instead of just focusing on one call. We recommend using “FlutterPhoneState.phoneCallEventStream” because it includes our own tracking logic, call timeouts, failures, etc.
watchAllPhoneCallEvents() {
FlutterPhoneState.phoneCallEvents.forEach((PhoneCallEvent event) {
final phoneCall = event.call;
print("Got an event $event");
});
print("That loop ^^ won't end");
}
You can sign up to get the raw events if you want to. Keep in mind that there are only so many of these events.
watchAllRawEvents() {
FlutterPhoneState.rawPhoneEvent.forEach((RawPhoneEvent event) {
final phoneCall = event.call;
print("Got an event $event");
});
print("That loop ^^ won't end");
Related
I'm using CameraX's image analysis use case that keeps calling the analyze() method in my custom Analyzer class. Inside analyze(), before doing anything else, I need to send a request to a connected device and wait for its response; the latency is very low and I'm already doing it synchronously with no issues, but I was told it's better to make it asynchronous just in case the device responds too slowly.
I know that MLKit's process() returns a Task<List<T>> and I already call onSuccessListener { } on it, so I was wondering if I can use a similar approach (I can't return a Task<T> from my function, how do I create one?). Otherwise would you suggest threads, or coroutines, or something else?
Edit: below there's a simplified example of what I'm trying to do. For a given frame sent by the camera I just need to perform only the current analysis in line, then I return so that analyze() will be called again with the next frame, on which it will perform the next analysis.
It might look hacky but it's for an app that continuously runs in foreground on a single-purpose device (let's call it Dev A) with no user interaction provided by touch or other conventional means, so it needs some kind of trigger to start doing what is required.
The trigger might as well be when the first image analysis in line is successful, but running MLKit or TFLite models from real time camera feed all day long makes Dev A overheat excessively. The best solution so far seems to be waiting for the trigger to come from an external device (Dev B) that operates independently.
Since Dev B may respond with some delay I need to communicate with it asynchronously, hence the reason for the question in the first place. While there are certainly several architectural nuances to discuss, the current root of the problem is that I can't decide (or rather I don't know) how to handle the repeating "connection" with Dev B in a non-blocking way.
I mean, can I just treat this issue like any other case where multithreading is needed, or the fact that the camera is involved might pose additional threats? The backpressure strategy is set to STRATEGY_KEEP_ONLY_LATEST, so in theory if the current call to analyze() hasn't finished yet the new frames are dropped and nothing bad happens even if inside the method I'm still waiting for the async call to Dev B to finish, or am I missing something?
var connected = false
lateinit var result: Boolean
var analysis1 = true
var analysis2 = true
override fun analyze() {
if (!connected) {
result = connectToDevice() // needs to be async
connected = true
}
// need positive result to proceed, otherwise start over
if (!result) {
connected = false
return
}
if (analysis1) {
// perform analysis #1...
analysis1 = false
// when an analysis is done, exit early and perform next analysis on next frame
return
}
if (analysis2) {
// perform analysis #2...
analysis2 = false
// same as above
return
}
// when all analyses are done, reset all flags to start over
connected = false
analysis1 = true
analysis2 = true
}
I am developing an application for my friend who is in sales, this application will make phone calls one after another, as soon as one phone call gets disconnected, it will automatically make call to another number from the list. This list can be read from and xml data source or json or mongodb or even from excel sheet.
This could be an ios app that reads data from an end point and stores them and can initiate the call at any point and it wont stop until all the calls are made.
Next call will be made only after the first call has been finished.
I am thinking about using node based web app using google voice to trigger the chain.
I've no experience with ios / android apis but Im willing to work on that if it's a viable thing on that platform.
Note: what we're trying to avoid is whole process of
looking up the phone number.
touch hangup and then click for another phone number.
It should self trigger the next call as soon as current call gets disconnected.
Also we're trying to avoid any paid services like twillo.
Thanks in advance :)
for IOS, you could use CTCallCenter
self.callCenter = [[CTCallCenter alloc] init];
self.callCenter.callEventHandler = ^(CTCall *call){
if ([call.callState isEqualToString: CTCallStateConnected])
{
//NSLog(#"call stopped");
}
else if ([call.callState isEqualToString: CTCallStateDialing])
{
}
else if ([call.callState isEqualToString: CTCallStateDisconnected])
{
//NSLog(#"call played");
}
else if ([call.callState isEqualToString: CTCallStateIncoming])
{
}
};
Download phone list, loop inside phone list, make a call, listening for CTCallCenter and appdelegate's Event, detect user have finish last call, our app active again, then make the next call.
Or you can try in Demo here !
I have an important question: I manage stream flow on my receiver but I want to use stop message from my sender for stop the stream. Currently I'm using this sender (https://github.com/googlecast/CastVideos-android) and this receiver (https://github.com/googlecast/CastReferencePlayer) but the problem is that the sender sends me a command to pause and not a stop during the live.
In the documentation, side sender Android, I'm reading that the behavior is correct and the receiver must send a media status update message back to the sender and should report the state as MediaStatus.PLAYER_STATE_IDLE with reason MediaStatus.IDLE_REASON_CANCELLED.
Arrived at this point I want to modify the sample receiver and manage the pause like a stop and not like a pause. I want to manage the stop because when the sender click the stop button the receiver must stop the video and the sender must destroy "every player" (player, miniplayer, etc).
So My idea is this:
sampleplayer.CastPlayer.prototype.onPause_ = function() {
this.log_('onPause');
this.cancelDeferredPlay_('media is paused');
var isIdle = this.state_ === sampleplayer.State.IDLE;
var isDone = this.mediaElement_.currentTime === this.mediaElement_.duration;
var isUnderflow = this.player_ && this.player_.getState()['underflow'];
if (isUnderflow) {
this.log_('isUnderflow');
this.setState_(sampleplayer.State.BUFFERING, false);
this.mediaManager_.broadcastStatus(/* includeMedia */ false);
} else if (!isIdle && !isDone) {
this.setState_(sampleplayer.State.PAUSED, false);
} else if(this.isLiveStream) {
this.log_('onStop');
this.cancelDeferredPlay_('media is stopped');
var self = this;
sampleplayer.transition_(self.element_, sampleplayer.TRANSITION_DURATION_,
function() {
self.setState_(sampleplayer.State.IDLE, false);
self.resetMediaElement_();
self.mediaManager_.setIdleReason("CANCELLED");
});
return ;
}
this.updateProgress_();
};
As you can see in the third branc, I control a variable that I saved during the load of the video and after I set the state of player to IDLE, reset the mediaElement and finally I send to broadcast the State = IDLE and Reason = CANCELLED. In this way the sender see the message because I look the log but doesn't interpret this.
Now I don't know how to continue and manage this behaviour. Advice are welcome. Thank you.
Just to make sure my answer is covering your question, let me simplify your questions as the following: when playing a live stream, you want to still see the "stop" button on the sender side but if the user taps on that button, you want to stop the playback and unload the media.
If this is correct, you can achieve that from the sender side as well: CastVideos-android uses CastCompanionLibrary. There are two places that you need to update in that library: in VideoCastManager#togglePlayback() and VideoCastControllerFragment#togglePlayback(). In the former place, you need to update the conditional there to read like the following:
if (isPlaying && isRemoteStreamLive()) {
stop();
} else if (isPlaying) {
pause();
} else {
... //leave as is
}
In the latter case, you need to update one of the switch statements:
case MediaStatus.PLAYER_STATE_PLAYING:
if (mSelectedMedia.getStreamType() == MediaInfo.STREAM_TYPE_LIVE) {
mCastManager.stop();
mPlaybackState = MediaStatus.PLAYER_STATE_IDLE;
} else {
mCastManager.pause();
mPlaybackState = MediaStatus.PLAYER_STATE_BUFFERING;
}
break;
Basically, you are adding a logic that if the content is playing remotely, "toggling playback" should call stop() rather than pause() when dealing with a live stream.
Note that calling stop() means you are completely unloading your media and you may need to do some additional work to play another media but I haven't tested that since I don't call stop() in the CastVideos app. Also note that I have not tested/tried the above suggestion since I don't have a live stream to play with but I am hoping it would work.
I have being upgrading an application to use the new Mobile Android GNSK but I have noticed that using the new MusicID-Stream is a little bit tricky. If the "identifyAlbumAsync" method get executed before the "audioProcessStart" method(since this need to be executed in a different thread), the application just crashes. In the Gracenote Demo application, the "audioProcessStart" method is continuously running so there is no need to synchronize its execution with the "identifyAlbumAsync" method call. Is it the way it is supposed to be used? It will be convenient if the application didn't crashed at least when the methods are not executed in order. Also in our application, we don't want to have the "audioProcessStart" method continuously like it is done in the demo application. We only want to run the "audioProcessStart" method when the user request identification and when the song playing gets identified , we want to stop the audio processing by calling "audioProcessStop". Is there an easy way to do this? Right now, we are getting the Thread where "identifyAlbumAsync" is running to sleep for 2 seconds in order to make sure that the Thread where the "audioProcessStart" method is supposed to run has time to get executed. Thank you in advance for your prompt response
In the upcoming 1.2 release, IGnMusicIdStreamEvents includes a callback that signals audio-processing has started, and an ID can be synced with this, e.g.:
#Override
public void musicIdStreamProcessingStatusEvent( GnMusicIdStreamProcessingStatus status, IGnCancellable canceller ) {
if (GnMusicIdStreamProcessingStatus.kStatusProcessingAudioStarted.compareTo(status) == 0) {
try {
gnMusicIdStream.identifyAlbumAsync();
} catch (GnException e) { }
}
}
Thanks for the feedback, you're right about this issue. Unfortunately right now sleeping is the best solution. But we are adding support for an explicit sync event in an upcoming release, please stay tuned.
Just a quick background I'm Running CM7 on a rooted Nexus one.
I am trying to detect when an outgoing call is actually connected: has stopped ringing and the person you are calling has answered. Looking through the forums this seems to be a tough and perhaps unanswered question. I'd really appreciate any insight into this.
In my searching the best I could find was in:
Android : How to get a state that the outgoing call has been answered?
#PattabiRaman said: "instead of detecting the outgoing call connection state, it is easy to get the duration of the last dialed call."
Does he mean that one should get the duration of the last dialed call as the call is in progress? And when that duration goes over 0 then you know?
The class com.android.internal.telephony.CallManager should have information about when the call actually is answered. It has a public static method getInstance() which returns the CallManager instance, and a public method getActiveFgCallState() which returns the current call state as a Call.State enum.
So in theory something like this might work:
Method getFgState = null;
Object cm = null;
try {
Class cmDesc = Class.forName("com.android.internal.telephony.CallManager");
Method getCM = cmDesc.getMethod("getInstance");
getFgState = cmDesc.getMethod("getActiveFgCallState");
cm = getCM.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}
And then repeatedly poll the state:
Object state = getFgState.invoke(cm);
if (state.toString().equals("IDLE")) {
...
} else if (state.toString().equals("ACTIVE")) {
// If the previous state wasn't "ACTIVE" then the
// call has been established.
}
I haven't verified that this actually works. And even if it does you'll have to keep in mind that the API could change, since this isn't something that app developers are supposed to rely on.
I have looked into the code.
It will always give null unless you instantiate a Phone object and set it as default Phone.
But instantiating it needs some System permissions allowed only to system aps.
By using this method:
com.android.internal.telephony.PhoneFactory# public static void makeDefaultPhones(Context context) {
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.4_r1.2/com/android/internal/telephony/PhoneFactory.java