Ich entwickle einen Broadcast-Empfänger für eingehende Anrufe in Android. Wenn Sie eingehende Anrufe erhalten, möchte ich ein Popup-Fenster über dem Bildschirm für eingehende Anrufe aufblasen.
Ich habe diesen Code vervollständigt. Aber jetzt ist das Problem, dass in der Android 4.1 (Jelly Bean) API Level 17 , wenn ein Telefon klingelt, der PHONE_STATE
als OFF HOOK
kommt, und wenn ich eine Aktivität anrufe, wird es aufgerufen, aber der Code darunter wird nicht ausgeführt. Ich gebe den Code auf:
package com.example.popwindowonincomingcallscreen;
import Java.util.concurrent.Executors;
import Java.util.concurrent.ScheduledExecutorService;
import Android.content.BroadcastReceiver;
import Android.content.Context;
import Android.content.Intent;
import Android.telephony.TelephonyManager;
import Android.util.Log;
public class IncomingBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("IncomingBroadcastReceiver: onReceive: ", "flag1");
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
Log.d("IncomingBroadcastReceiver: onReceive: ", state);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)
|| state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
Log.d("Ringing", "Phone is ringing");
Intent i = new Intent(context, IncomingCallActivity.class);
i.putExtras(intent);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
Wait.oneSec();
context.startActivity(i);
}
}
}
Und die Tätigkeit, die ich anrufe:
import Android.app.Activity;
import Android.os.Bundle;
import Android.telephony.TelephonyManager;
import Android.util.Log;
import Android.view.View.MeasureSpec;
import Android.view.Window;
import Android.view.WindowManager;
import Android.widget.TextView;
public class IncomingCallActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
try {
Log.d("IncomingCallActivity: onCreate: ", "flag2");
*/ After this line, the code is not executed in Android 4.1 (Jelly bean) only/*
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
Log.d("IncomingCallActivity: onCreate: ", "flagy");
setContentView(R.layout.main);
Log.d("IncomingCallActivity: onCreate: ", "flagz");
String number = getIntent().getStringExtra(
TelephonyManager.EXTRA_INCOMING_NUMBER);
TextView text = (TextView) findViewById(R.id.text);
text.setText("Incoming call from " + number);
}
catch (Exception e) {
Log.d("Exception", e.toString());
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Nach dem
try {
Log.d("IncomingCallActivity: onCreate: ", "flag2");
}
Der Code wird in Android 4.1 (Jelly Bean) nicht ausgeführt, aber in anderen Versionen funktioniert er.
Ich habe fast alle Möglichkeiten ausprobiert. Dieser Code zeigt eine durchscheinende Aktivität über dem Bildschirm für den ursprünglichen Anruf an und blockiert nicht die Hintergrundsteuerelemente, wie z. B. das Abheben des Telefons. Aber ich will es wie ein echter Anrufer. Ich habe eine Momentaufnahme dazu angefügt, wie der echte Anrufer ein Fenster auf dem Bildschirm für eingehende Anrufe anzeigt.
Wie kann ich diese Funktionalität für eine Android-App erreichen?
So funktioniert ein echter Anrufer:
Meine derzeitige Ausgabe:
Nach Kopfgeld bekomme ich auch nicht genau das, wonach ich suche, aber ich werde auf alle zurückkommen; Ich arbeite daran. Auf jeden Fall funktioniert dieser Code für die meisten Android-Handys. Wenn jemand die Lösung dafür einsetzen und einholen möchte, schreiben Sie bitte hier, damit alle davon profitieren können.
Ich habe versucht, Toast in der onReceive-Methode des Broadcast-Empfängers zu implementieren, da Toast eine native Komponente von Android ist, aber auch in Android 4.1 (Jelly Bean) nicht angezeigt wird.
Meine Idee war, Toast in die onReceive-Methode des Rundfunkempfängers zu implementieren und anschließend das Design an unsere Bedürfnisse anzupassen und die Anzeigedauer anzupassen. Ein weiteres Problem ist jedoch, dass findViewById im Broadcast-Empfänger nicht funktioniert. Ich denke, wir müssen ein LinearLayout programmgesteuert erstellen, um den Toast anzupassen.
Ich bin nicht sicher, ob Ihre benutzerdefinierte GUI immer über der Standardeinstellung liegt, da der Broadcast-Receiver des Systems und Ihr Receiver beide versuchen, die GUI oben auf dem Bildschirm anzuzeigen. Wir sind nicht sicher, welche zuerst aufgerufen wird, aber eine knifflige Arbeit, um Ihre GUI oben auf dem Bildschirm anzuzeigen, ist, wenn das Telefon klingelt, rufen Sie Ihre Aktivität nach 1-2 Sekunden (s) des verwendeten Handlers an.
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Intent intent = new Intent(context, AcceptReject.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
}, 2000);
Ich hoffe es kann dir helfen.
Versuchen Sie den Code vor der super.onCreate
-Methode. Ich denke, nach dem Aufruf des Super wird der Code übersprungen. Irgendwann funktionierten diese Tricks für mich.
Ich habe gerade auf dem Emulator Android 4.2 (Jelly Bean) getestet, und es funktioniert perfekt, indem es den gesamten Bildschirm für eingehende Anrufe blockiert, genau wie bei truecaller:
public void onReceive(Context context, Intent intent) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT |
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSPARENT);
params.height = LayoutParams.MATCH_PARENT;
params.width = LayoutParams.MATCH_PARENT;
params.format = PixelFormat.TRANSLUCENT;
params.gravity = Gravity.TOP;
LinearLayout ly = new LinearLayout(context);
ly.setBackgroundColor(Color.RED);
ly.setOrientation(LinearLayout.VERTICAL);
wm.addView(ly, params);
}
Im Manifest:
<receiver Android:name="" Android:enabled="true" >
<intent-filter Android:priority="-1">
<action Android:name="Android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
Ich versuche etwas Ähnliches und füge dem Bildschirm für eingehende Anrufe eine zusätzliche Schaltfläche hinzu.
Die von Sam Adams veröffentlichte Antwort funktioniert für mich, obwohl ich den Code von einem PhoneStateListener anrufe. Abgesehen davon ist der einzige wirkliche Unterschied zu seinem Code das Aufblasen eines Layouts:
overlay = (RelativeLayout) inflater.inflate(R.layout.overlay, null);
wm.addView(overlay, params);
Es funktioniert sowohl an Emulatoren als auch an einem HTC One S (mit Android 4.1.1).
Denken Sie daran, dass Sie einen Verweis auf die hinzugefügte Overlay-Ansicht behalten und sie wieder entfernen (Aufruf removeView () für Windowmanager-Instanz), wenn das Telefon wieder in den Ruhezustand wechselt (wenn der Listener TelephonyManager.CALL_STATE_IDLE erhält), andernfalls Ihr Overlay bleibt auf dem Bildschirm.
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
if(overlay!=null)
{
wm.removeView(overlay);
overlay = null;
}
Ich denke, Sie sollten keine Aktivität beginnen, um das beschriebene Ergebnis zu erzielen. Sie benötigen eine separate Ansicht mit LayoutParams.TYPE_SYSTEM_OVERLAY
in den Layoutparametern.
Sie können diese Ansicht an einem beliebigen Ort auf dem Bildschirm positionieren oder den gesamten Bildschirm abdecken.
Hier sind einige Codezeilen:
_av = new ActivatorView(this);
_avLayoutParams = new WindowManager.LayoutParams(0, 0, 0, 0,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
PixelFormat.OPAQUE);
_avLayoutParams.screenBrightness = _fScreenBrightness = 20f;
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(_av, _avLayoutParams);
https://bitbucket.org/gyrussolutions/yaab/src/f01cc8aff690cae1b1107287cb17835b8a3c1643/src/biz/gyrus/yaab/LightMonitorService.java?at=default#cl-338 - die vollständige Quelltextdatei.
Ich arbeite auch daran (ich kann es falsch machen, Sie hier zu verstehen). Sie möchten diese Aktivität in Android 4.2 (Jelly Bean) anzeigen. Ich habe nur eine Verzögerung gesetzt, um die Aktivität anzuzeigen. Ich habe PhoneStateListener in verschiedenen Klassen verwendet. Ich kann neue Aktivitäten auf dem Anruferbildschirm anzeigen. Hier ist mein vollständiger Code:
public class MyBroadcastReceiver extends BroadcastReceiver {
static CustomPhoneStateListener phoneStateListener;
Context context;
Intent intent;
@Override
public void onReceive(Context context, Intent intent) {
this.context = context;
this.intent = intent;
// TODO Auto-generated method stub
TelephonyManager telephonyManager = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
phoneStateListener = new CustomPhoneStateListener(context);
telephonyManager.listen(phoneStateListener,
PhoneStateListener.LISTEN_CALL_STATE);
}
}
public class CustomPhoneStateListener extends PhoneStateListener {
// private static final String TAG = "PhoneStateChanged";
Context context; // Context to make Toast if required
private AudioManager amanager;
Intent i1;
public CustomPhoneStateListener(Context context) {
super();
this.context = context;
i1 = new Intent(context, YourActivity.class);
i1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
}
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
Toast.makeText(context, "Phone state Idle", Toast.LENGTH_LONG)
.show();
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Toast.makeText(context, "Phone state Off hook", Toast.LENGTH_LONG)
.show();
break;
case TelephonyManager.CALL_STATE_RINGING:
try {
Thread.sleep(3000);
context.startActivity(i1);
} catch (Exception e) {
e.getLocalizedMessage();
}
default:
break;
}
}
und YourActivity bleibt so, wie Sie es erstellt haben ... Hinweis: Ich habe auch in diesem Code einige Probleme, da sie hier sind.
(Hilfe für diese Probleme akzeptiert. Danke. Könnte jemandem helfen)
UPDATE
HIER IS LINK OF KLEINE DEMO SO ERREICHEN SIE DAS.
Wir hatten auch ein ähnliches Problem, dass das Overlay nicht auf einem Gerät mit Pin Lock angezeigt wurde. Die Lösung, die für uns funktioniert hat, ist unten:
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
mParams = new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT,
LayoutParams.TYPE_SYSTEM_ERROR,
LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
Es war LayoutParams.TYPE_SYSTEM_ERROR
, der den Unterschied machte.
Meine Methode:
verwenden Sie den Dienst, um das Overlay zu erstellen
ps:wmParams.type = WindowManager.LayoutParams.TYPE_PHONE;
versuche dies
AlertDialog.Builder builder = new AlertDialog.Builder(context.getApplicationContext());
LayoutInflater inflater = LayoutInflater.from(context);
View dialogView = inflater.inflate(R.layout.caller_dialog, null);
ImageView button = dialogView.findViewById(R.id.close_btn);
builder.setView(dialogView);
final AlertDialog alert = builder.create();
alert.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
alert.getWindow().setType(WindowManager.LayoutParams.TYPE_PHONE);
alert.setCanceledOnTouchOutside(true);
alert.show();
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
Window window = alert.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
window.setGravity(Gravity.TOP);
lp.copyFrom(window.getAttributes());
//This makes the dialog take up the full width
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
window.setAttributes(lp);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//close the service and remove the from from the window
alert.dismiss();
}
});
Verwenden Sie einen einfachen Broadcast-Empfänger und geben Sie diesen Code in den Broadcast-Empfänger ein
public void onReceive(final Context context, final Intent intent) {
Log.v(LOG_TAG, "Receieved notification about network status");
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT |
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSPARENT);
params.height = WindowManager.LayoutParams.MATCH_PARENT;
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.format = PixelFormat.TRANSLUCENT;
params.gravity = Gravity.TOP;
LinearLayout ly = new LinearLayout(context);
ly.setBackgroundColor(Color.RED);
ly.setOrientation(LinearLayout.VERTICAL);
wm.addView(ly, params);
}
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Intent i = new Intent(context, CallingIncoming.class);
i.putExtras(intent);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK /*| Intent.FLAG_ACTIVITY_CLEAR_TASK*/);
context.startActivity(i);
}
}, 450);//It will help you to delay your screen and after it your screen will be top of default app screen