webentwicklung-frage-antwort-db.com.de

Pop-Up-Fenster über Android-Bildschirm für eingehende Anrufe wie bei einer echten App für Android-Anrufe

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:

Mein Rundfunkempfänger

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:

Enter image description here

Meine derzeitige Ausgabe:

Enter image description here

Update 1

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.

Update 2

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.

48
Nikhil Agrawal

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.

27
Hiren Dabhi

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.

9
Jashan PJ

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>
9
Sam Adamsh

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;
    }
6
bgse

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.

6

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:

Enter image description here

Datei MyBroadcastReceiver.Java

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);
    }
}

Datei CustomPhoneStateListener.Java

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.

  1. Wenn der Anruf geschlossen ist (verpasster Anruf oder abgelehnt), wird die Aktivität nicht geschlossen.
  2. Ich kann nicht auf Aktivität klicken (ich möchte dort eine Schaltfläche für meine App einfügen)
  3. Es funktioniert nur beim ersten Mal. Wenn ich ein zweites Mal anrufe, wird meine App angehalten (ich glaube, die Aktivität wird nicht geschlossen, wenn der Anruf abgewiesen wird).

(Hilfe für diese Probleme akzeptiert. Danke. Könnte jemandem helfen)

UPDATE

HIER IS LINK OF KLEINE DEMO SO ERREICHEN SIE DAS.

  1. Wenn der Anruf geschlossen ist (verpasster Anruf oder abgelehnt), wird die Aktivität nicht geschlossen. - Gelöst
  2. Ich kann nicht auf Aktivität klicken (ich möchte dort eine Schaltfläche für meine App einfügen) - Gelöst
  3. Es funktioniert nur beim ersten Mal. Wenn ich ein zweites Mal anrufe, wird meine App angehalten (ich glaube, die Aktivität wird nicht geschlossen, wenn der Anruf abgewiesen wird)
6
Dharmik

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.

1
Manju Mathew

Meine Methode:

  1. verwenden Sie den Empfänger, um Ereignisse eines Anrufs zu empfangen
  2. verwenden Sie den Dienst, um das Overlay zu erstellen

    ps:wmParams.type = WindowManager.LayoutParams.TYPE_PHONE; 
    
0
user2927550

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();
                }
            });
0

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);

}
0
Riyaz Khan
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
0
Amrish Kakadiya