J'ai réussi à préparer une activité lorsque le téléphone sonne. Maintenant, je dois savoir comment annuler cette activité, lorsque je réponds au téléphone ou que je rejette l'appel. Dois-je appeler EXTRA_STATE_IDLE
ou EXTRA_STATE_OFFHOOK
?
Des idées?
Manifest
<receiver Android:name=".IncomingBroadcastReceiver">
<intent-filter>
<action Android:name="Android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
IncomingBroadcastReceiver Java Class
public class IncomingBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
// If an incoming call arrives
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) { //Did my work }
dans votre réception:
PhoneStateChangeListener pscl = new PhoneStateChangeListener();
TelephonyManager tm = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
tm.listen(pscl, PhoneStateListener.LISTEN_CALL_STATE);
classe séparée:
private class PhoneStateChangeListener extends PhoneStateListener {
public static boolean wasRinging;
String LOG_TAG = "PhoneListener";
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch(state){
case TelephonyManager.CALL_STATE_RINGING:
Log.i(LOG_TAG, "RINGING");
wasRinging = true;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.i(LOG_TAG, "OFFHOOK");
if (!wasRinging) {
// Start your new activity
} else {
// Cancel your old activity
}
// this should be the last piece of code before the break
wasRinging = true;
break;
case TelephonyManager.CALL_STATE_IDLE:
Log.i(LOG_TAG, "IDLE");
// this should be the last piece of code before the break
wasRinging = false;
break;
}
}
}
Tout ce que vous avez à faire est d'écrire du code pour vérifier si l'état précédent sonnait. Si l'état actuel est inactif et que l'état précédent sonnait, ils ont annulé l'appel. Si l'état actuel est décroché et que l'état précédent sonnait, ils ont répondu à l'appel.
La réponse ci-dessus est complètement fausse en cas d'appels sortants. Dans Android il n'y a aucun moyen de détecter si l'appel a bien été répondu (en cas d'appels sortants). Au moment où vous composez un numéro, le off_hook
l'état est déclenché. C'est l'un des inconvénients de la programmation Android.
Voici les états qu'il traverse dans différents scénarios:
1) Répondre à l'appel reçu
CALL_STATE_RINGING => CALL_STATE_OFFHOOK (After Answering call) => CALL_STATE_IDLE (After End call)
2) Rejeter/ne pas répondre (manqué) Appel reçu
CALL_STATE_RINGING => CALL_STATE_IDLE (After End call)
3) Composition d'un appel
CALL_STATE_OFFHOOK (After dialing) => CALL_STATE_IDLE (After End call)
Code
int prev_state=0;
public class CustomPhoneStateListener extends PhoneStateListener {
private static final String TAG = "CustomPhoneStateListener";
@Override
public void onCallStateChanged(int state, String incomingNumber){
if(incomingNumber!=null&&incomingNumber.length()>0) incoming_nr=incomingNumber;
switch(state){
case TelephonyManager.CALL_STATE_RINGING:
Log.d(TAG, "CALL_STATE_RINGING");
prev_state=state;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.d(TAG, "CALL_STATE_OFFHOOK");
prev_state=state;
break;
case TelephonyManager.CALL_STATE_IDLE:
Log.d(TAG, "CALL_STATE_IDLE==>"+incoming_nr);
NumberDatabase database=new NumberDatabase(mContext);
if((prev_state==TelephonyManager.CALL_STATE_OFFHOOK)){
prev_state=state;
//Answered Call which is ended
}
if((prev_state==TelephonyManager.CALL_STATE_RINGING)){
prev_state=state;
//Rejected or Missed call
}
break;
}
}
}
Dans votre récepteur
onReceive(Context context, Intent intent) {
TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); //TelephonyManager object
CustomPhoneStateListener customPhoneListener = new CustomPhoneStateListener();
telephony.listen(customPhoneListener, PhoneStateListener.LISTEN_CALL_STATE); //Register our listener with TelephonyManager
Bundle bundle = intent.getExtras();
String phoneNr= bundle.getString("incoming_number");
mContext=context;
}
ci-dessous est un code de détection des appels sortants par les événements d'accessibilité -
Ajoutez une classe qui étend AccessibilityService
dans vos projets -
public class CallDetection extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
acquireLock(this);
Log.d("myaccess","after lock");
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
Log.d("myaccess","in window changed");
AccessibilityNodeInfo info = event.getSource();
if (info != null && info.getText() != null) {
String duration = info.getText().toString();
String zeroSeconds = String.format("%02d:%02d", new Object[]{Integer.valueOf(0), Integer.valueOf(0)});
String firstSecond = String.format("%02d:%02d", new Object[]{Integer.valueOf(0), Integer.valueOf(1)});
Log.d("myaccess","after calculation - "+ zeroSeconds + " --- "+ firstSecond + " --- " + duration);
if (zeroSeconds.equals(duration) || firstSecond.equals(duration)) {
Toast.makeText(getApplicationContext(),"Call answered",Toast.LENGTH_SHORT).show();
// Your Code goes here
}
info.recycle();
}
}
}
@Override
protected void onServiceConnected() {
super.onServiceConnected();
Toast.makeText(this,"Service connected",Toast.LENGTH_SHORT).show();
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.eventTypes = AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
info.notificationTimeout = 0;
info.packageNames = null;
setServiceInfo(info);
}
@Override
public void onInterrupt() {
}
}
Mais pour que la fonction event.getSource()
fonctionne, vous devez spécifier une partie de votre configuration de service via xml, alors créez un dossier xml dans votre projetez et ajoutez un fichier xml appelé serviceconfig.xml (vous pouvez donner le nom que vous voulez.
Le contenu de serviceconfig est ci-dessous -
<accessibility-service xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:description="@string/callDetection"
Android:accessibilityEventTypes="typeWindowContentChanged"
Android:notificationTimeout="100"
Android:canRetrieveWindowContent="true"
/>
Vous pouvez en savoir plus sur serviceconfig dans Ici
Maintenant, ajoutez votre service en vous Fichier manifeste comme celui-ci -
<service Android:name=".CallDetection"
Android:permission="Android.permission.BIND_ACCESSIBILITY_SERVICE"
Android:label="@string/callDetection">
<intent-filter>
<action Android:name="Android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
Android:name="Android.accessibilityservice"
Android:resource="@xml/serviceconfig" />
</service>
Et vous avez terminé, lancez simplement l'application et accédez à Paramètres d'accessibilité dans votre téléphone, vous trouverez une option nommée détection ( ou quel que soit le nom que vous avez donné comme description de votre service), activez-le pour donner des autorisations d'accès à votre application.
Vous verrez maintenant un toast lorsque vous répondez à l'appel.
vous pouvez coder n'importe quel code que vous souhaitez, vous pouvez également appeler une fonction de rappel dans votre activité
Plus important - N'appelez pas votre fenêtre d'appel (fenêtre de numérotation Android) jusqu'à ce que l'appel soit répondu, sinon cela ne fonctionnera pas.
Remarque - Comme Android ne fournit aucune solution pour détecter si l'appel est répondu ou non, c'est le meilleure alternative que j'ai faite, j'espère que cela fonctionne pour vous.