android - एंड्रॉइड मूल आने वाली कॉल स्क्रीन पर सच्ची कॉलर एंड्रॉइड ऐप की तरह विंडो पॉप अप करें




android-layout android-widget (8)

इसे इस्तेमाल करे

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

मैं एंड्रॉइड में आने वाली कॉल के लिए एक प्रसारण रिसीवर विकसित कर रहा हूं और आने वाली कॉल प्राप्त करने पर मैं मूल आने वाली कॉल स्क्रीन पर पॉप अप करना चाहता हूं।

मैंने वह कोड पूरा किया। लेकिन अब समस्या यह है कि एंड्रॉइड 4.1 (जेली बीन) एपीआई लेवल 17 में जब कोई फ़ोन रिंग करता है, तो PHONE_STATE OFF HOOK रूप में आ रहा है, और यदि मैं एक गतिविधि बुला रहा हूं, तो इसे कॉल किया जाता है, लेकिन इसके तहत कोड नहीं होता है निष्पादित हो जाओ। मैं कोड सूचीबद्ध कर रहा हूं:

मेरा प्रसारण रिसीवर

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

एक गतिविधि जिसे मैं बुला रहा हूं:

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

बाद

try {
    Log.d("IncomingCallActivity: onCreate: ", "flag2");
}

कोड एंड्रॉइड 4.1 (जेली बीन) में निष्पादित नहीं हो रहा है, लेकिन अन्य संस्करणों में यह काम कर रहा है।

मैंने लगभग सभी तरीकों का प्रयास किया है जो मैं कर सकता हूं। यह कोड देशी कॉल स्क्रीन पर एक पारदर्शी गतिविधि प्रदर्शित कर रहा है, और यह फ़ोन को चुनने जैसी पृष्ठभूमि नियंत्रण को अवरुद्ध नहीं करता है। लेकिन मैं इसे सच कॉलर की तरह चाहता हूं। मैंने स्नैपशॉट संलग्न किया है कि कैसे सही कॉलर आने वाली कॉल स्क्रीन पर एक विंडो प्रदर्शित कर रहा है।

एंड्रॉइड ऐप के लिए मैं इस कार्यक्षमता को कैसे प्राप्त कर सकता हूं?

इस तरह एक सच्चा कॉलर काम करता है:

मेरा वर्तमान आउटपुट:

अद्यतन 1

बक्षीस के बाद भी मुझे वह सटीक चीज़ नहीं मिल रही है जिसे मैं ढूंढ रहा हूं, लेकिन मैं वापस आऊंगा; मैं इस पर काम कर रहा हूँ। वैसे भी, यह कोड अधिकांश एंड्रॉइड फोन के लिए काम करता है। यदि कोई इसका उपयोग करने और उसके लिए समाधान पकड़ने जा रहा है, तो कृपया यहां लिखें ताकि सभी को लाभ मिल सके।

अद्यतन 2

मैंने प्रसारण रिसीवर की ऑनसाइट विधि में टोस्ट को लागू करने की कोशिश की क्योंकि टोस्ट एंड्रॉइड का मूल घटक है, लेकिन यह एंड्रॉइड 4.1 (जेली बीन) में भी प्रदर्शित नहीं हो रहा है।

मेरा विचार था कि प्रसारण रिसीवर की ऑनसीसेव विधि में टोस्ट को लागू करना और बाद में अपनी जरूरतों के अनुसार अपना डिज़ाइन बदलना और प्रदर्शन की अवधि को ट्यून करना था। लेकिन एक और समस्या यह है कि findViewById प्रसारण रिसीवर में काम नहीं करता है, इसलिए मुझे लगता है कि हमें टोस्ट को अनुकूलित करने के लिए प्रोग्रामर रूप से एक रैखिक स्तर बनाना होगा।


एक साधारण प्रसारण रिसीवर का उपयोग करें और इस कोड को प्रसारण रिसीवर में रखें:

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

}

मुझे लगता है कि आपको वर्णित परिणाम प्राप्त करने के लिए गतिविधि शुरू नहीं करनी चाहिए। आपको लेआउट LayoutParams.TYPE_SYSTEM_OVERLAY एक अलग दृश्य की LayoutParams.TYPE_SYSTEM_OVERLAYLayoutParams.TYPE_SYSTEM_OVERLAY अपने लेआउट LayoutParams.TYPE_SYSTEM_OVERLAY सेट है।

आप स्क्रीन पर जहां भी चाहें इस दृश्य को स्थिति में रख सकते हैं, या बस पूरी स्क्रीन को कवर कर सकते हैं।

कोड की कुछ पंक्तियां यहां दी गई हैं:

 _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 - पूर्ण स्रोत कोड, इसे नमूना मानें।


मेरी विधि:

  1. फोन कॉल की घटनाओं को प्राप्त करने के लिए रिसीवर का उपयोग करें
  2. ओवरले बनाने के लिए सेवा का उपयोग करें

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

मैं भी इस पर काम कर रहा हूं (मुझे यहां आपको समझना गलत हो सकता है)। आप जो हासिल करना चाहते हैं वह एंड्रॉइड 4.2 (जेली बीन) में उस गतिविधि को प्रदर्शित करना है। मैंने गतिविधि को प्रदर्शित करने में देरी की है। मैंने विभिन्न वर्गों में फोनस्टेट लिस्टर का उपयोग किया है। मैं कॉलर स्क्रीन पर नई गतिविधि प्रदर्शित करने में सक्षम हूं। मेरा पूरा कोड यहां है:

फ़ाइल 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);
    }
}

फ़ाइल 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;
        }
    }

और आपकी सक्रियता बनी रहेगी जैसा आपने बनाया है ... नोट: मुझे इस कोड में कुछ समस्याएं भी आ रही हैं, वे यहां हैं।

  1. जब कॉल बंद हो जाता है तो क्लोज़ (मिस्ड कॉल या अस्वीकार) गतिविधि बंद नहीं होती है।
  2. मैं गतिविधि पर क्लिक करने में सक्षम नहीं हूं (मैं अपने ऐप के लिए एक बटन रखना चाहता हूं)
  3. यह केवल पहली बार काम करता है। जब मैं दूसरी बार फोन करता हूं, तो मेरा ऐप बंद हो जाता है (मुझे लगता है कि ऐसा इसलिए है क्योंकि जब कॉल खारिज कर दिया जाता है तो गतिविधि बंद नहीं होती है)

(इन समस्याओं के लिए सहायता स्वीकार की गई। धन्यवाद। किसी की मदद कर सकते हैं)

अद्यतन करें

यहां छोटे डेमो का लिंक कैसे प्राप्त किया गया है।

  1. जब कॉल बंद हो जाता है तो क्लोज़ (मिस्ड कॉल या अस्वीकार) गतिविधि बंद नहीं होती है। - हल किया
  2. मैं गतिविधि पर क्लिक करने में सक्षम नहीं हूं (मैं अपने ऐप के लिए एक बटन रखना चाहता हूं) - हल किया गया
  3. यह केवल पहली बार काम करता है। जब मैं दूसरी बार कॉल करता हूं, तो मेरा ऐप बंद हो जाता है (मुझे लगता है कि ऐसा इसलिए है क्योंकि कॉल को खारिज करते समय गतिविधि बंद नहीं की जा रही है) - हल किया गया

मैंने अभी एंड्रॉइड 4.2 (जेली बीन) एमुलेटर पर परीक्षण किया है, और यह पूरी आने वाली कॉल स्क्रीन को केवल 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);
}

मेनिफेस्ट में:

<receiver android:name=""  android:enabled="true" >
    <intent-filter android:priority="-1">
        <action android:name="android.intent.action.PHONE_STATE" />
    </intent-filter>
</receiver>

super.onCreate विधि से पहले कोड आज़माएं। मुझे लगता है कि सुपर कॉल करने के बाद कोड छोड़ दिया गया है। कभी-कभी इस तरह की चाल मेरे लिए काम करती है।


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