Some mobile phones will have a vibration prompt after the phone is connected. One advantage is that you can wait until it is connected and then put it in your ear to answer, reducing radiation. This article will talk about how to implement this vibration prompt function after connecting to a phone in an Android phone, which is mainly aimed at outgoing calls.
Call status provided by the Android SDK
It is obvious that to generate a vibration prompt when the phone is connected, you must first know when the phone is connected. The Android SDK does not provide a way to directly read this state. Here are three phone statuses provided by TelephonyManager, the phone service class of Android SDK:
CALL_STATE_IDLE Idle status
CALL_STATE_OFFHOOK Off-hook status
CALL_STATE_RINGING Ring status
These states are easy to understand: the off-hook state means picking up the microphone (an action for landline phones), but this state may occur when the incoming phone is connected or when the outgoing phone is transferred, but it cannot indicate when the outgoing phone is connected. Through the above three states, we can only combine the two states: hanging up and incoming call. But today the functions we want to implement cannot be achieved.
It seems that we need to find other ways to implement it, the SDK is unreliable...
Android running log analysis
Fortunately, Android will generate a large number of logs when running. See if we can find the blast from this? We chose Android's Radio module log for analysis. First of all, we need to write a piece of code to read the Radio-related log. If we read the log, we have to use logcat.
Process process; InputStream inputstream; BufferedReader bufferedreader; try { process = ().exec("logcat -v time -b radio"); inputstream = (); InputStreamReader inputstreamreader = new InputStreamReader( inputstream); bufferedreader = new BufferedReader(inputstreamreader); String str = ""; while ((str = ()) != null) { ("mLogcat",str); } } catch (Exception e) { }
In addition, to enable the program to read the system log, you need to specify permissions and add some content to the file.
XML/HTML Code
<uses-permission android:name=".READ_LOGS"></uses-permission>
Through the above code, we can output Radio's logs, so that we can view these logs in DDMS and analyze the call process. The specific logs you caught will not be posted. You can write your own program to capture and analyze them through the above code. I will only talk about my analysis results.
Through analysis of the log, some clues were found. Several of these logs are useful:
GET_CURRENT_CALLS id=1,DIALING
GET_CURRENT_CALLS id=1,ALERTING
GET_CURRENT_CALLS id=1,ACTIVE
Since the log is longer, I only took the beginning of each log, and there will be a lot more content in the real one. When we dial out the phone, we will enter these logs.
Dial->Reminder->Activities
This is roughly the process. After several tests, we found that when the phone is connected, it will enter an active state and output: GET_CURRENT_CALLS id=1,ACTIVE This log is almost successful.
However, I later found that the state change of "Dial->Reminder->Activity" will occur several times between the time when dialing starts and phone calls are connected. Only when the beep in the microphone sounds, the GET_CURRENT_CALLS log will be locked in ALERTING. The GET_CURRENT_CALLS log no longer appears before the phone is connected.
Maybe everyone is not very clear about the above statement. In other words, logs such as GET_CURRENT_CALLS ACTIVE will appear multiple times before the call is connected, and only once is generated by the phone is connected. This causes us trouble. You can't just simply grab information like GET_CURRENT_CALLS ACTIVE to judge.
We can only achieve it through some logical judgments.
Example code explanation
Let’s see my code below:
class TestThread implements Runnable { //Vibrator Vibrator mVibrator; //Telectronic service TelephonyManager telManager; public TestThread(Vibrator mVibrator, TelephonyManager telManager) { = mVibrator; = telManager; } @Override public void run() { //Get the current phone status int callState = (); ("TestService", "start.........." + ().getName()); //Record dialing start time long threadStart = (); Process process; InputStream inputstream; BufferedReader bufferedreader; try { process = ().exec("logcat -v time -b radio"); inputstream = (); InputStreamReader inputstreamreader = new InputStreamReader( inputstream); bufferedreader = new BufferedReader(inputstreamreader); String str = ""; long dialingStart = 0; boolean enableVibrator = false; boolean isAlert = false; while ((str = ()) != null) { //If the phone status changes from off-hook to idle, destroy the thread if (callState == TelephonyManager.CALL_STATE_OFFHOOK && () == TelephonyManager.CALL_STATE_IDLE) { break; } // The thread will be automatically destroyed after running for 5 minutes if (() - threadStart > 300000) { break; } ("TestService", ().getName() + ":" + str); // Record GSM status DIALING if (("GET_CURRENT_CALLS") && ("DIALING")) { // When DIALING starts and has passed ALERTING or the first DIALING if (!isAlert || dialingStart == 0) { //Record the DIALING status generation time dialingStart = (); isAlert = false; } continue; } if (("GET_CURRENT_CALLS") && ("ALERTING")&&!enableVibrator) { long temp = () - dialingStart; isAlert = true; //This is the key. When the time of the first DIALING state is more than 1.5 seconds and within 20 seconds, the interval between the current ALERTING is more than 1.5 seconds and less than 20 seconds. //Then think that the next ACTIVE status is called to be connected. if (temp > 1500 && temp < 20000) { enableVibrator = true; ("TestService", "Interval time..." + temp + "....." + ().getName()); } continue; } if (("GET_CURRENT_CALLS") && ("ACTIVE") && enableVibrator) { (100); enableVibrator = false; break; } } ("TestService", "Finish.........." + ().getName()); } catch (Exception e) { // TODO: handle exception } } }
My method is quite far-fetched. It is to judge the interval between the first DIALING and each ALERTING. If the interval is greater than 1.5 seconds, it is believed that it has entered the "beep" prompt, and the next ACTIVE will be the phone to be connected. This 1.5 seconds is derived from analyzing the log. But I always think this method is not reliable. If you have a good way, you can communicate.
All that remains is to let this thread trigger when the phone is dialed, and prepare it when it is always on the phone. Service can be used with Receiver to achieve it. Service is used to implement permanent resident, and Receiver is used to implement monitoring and outgoing calls. Basically, we can complete the functions we want.
I have tested all the above codes, and they are 99% valid, haha. Here we mention some basic contents of Android, such as logcat, Service, and Receiver. If you don’t understand these, you can find relevant articles and materials to learn.
Through this article, I hope to help Android development friends. Thank you for your support for this website!