একটি অ্যান্ড্রয়েড ডিভাইসে কীভাবে ইনকামিং কলগুলি সনাক্ত করা যায়?


130

আমি একটি অ্যাপ্লিকেশন তৈরি করার চেষ্টা করছি, যখন ফোনে কোনও কল আসে আমি নম্বরটি সনাক্ত করতে চাই। নীচে আমি যা চেষ্টা করেছি তা কিন্তু এটি আগত কলগুলি সনাক্ত করছে না।

আমি আমার MainActivityব্যাকগ্রাউন্ডে চালাতে চাই , আমি কীভাবে এটি করতে পারি?

আমি manifestফাইলটিতে অনুমতি দিয়েছিলাম ।

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

ম্যানিফেস্টে আমার অন্য কিছু সরবরাহ করা উচিত?

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test_layout);
   }

   public class myPhoneStateChangeListener extends PhoneStateListener {
       @Override
       public void onCallStateChanged(int state, String incomingNumber) {
           super.onCallStateChanged(state, incomingNumber);
           if (state == TelephonyManager.CALL_STATE_RINGING) {
               String phoneNumber =   incomingNumber;
           }
       }
   }
}

অ্যান্ড্রয়েড পি এর জন্য আমাদের কী করা উচিত
আহমদ আরসালান

উত্তর:


336

আমি এটি করতে এখানে যা ব্যবহার করি তা এখানে:

সুস্পষ্ট:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>

<!--This part is inside the application-->
    <receiver android:name=".CallReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.PHONE_STATE" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
        </intent-filter>
    </receiver>

আমার বেস পুনরায় ব্যবহারযোগ্য কল ডিটেক্টর

package com.gabesechan.android.reusable.receivers;

import java.util.Date;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;

public abstract class PhonecallReceiver extends BroadcastReceiver {

    //The receiver will be recreated whenever android feels like it.  We need a static variable to remember data between instantiations

    private static int lastState = TelephonyManager.CALL_STATE_IDLE;
    private static Date callStartTime;
    private static boolean isIncoming;
    private static String savedNumber;  //because the passed incoming is only valid in ringing


    @Override
    public void onReceive(Context context, Intent intent) {

        //We listen to two intents.  The new outgoing call only tells us of an outgoing call.  We use it to get the number.
        if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {
            savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER");
        }
        else{
            String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
            String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
            int state = 0;
            if(stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)){
                state = TelephonyManager.CALL_STATE_IDLE;
            }
            else if(stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
                state = TelephonyManager.CALL_STATE_OFFHOOK;
            }
            else if(stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)){
                state = TelephonyManager.CALL_STATE_RINGING;
            }


            onCallStateChanged(context, state, number);
        }
    }

    //Derived classes should override these to respond to specific events of interest
    protected abstract void onIncomingCallReceived(Context ctx, String number, Date start);
    protected abstract void onIncomingCallAnswered(Context ctx, String number, Date start);
    protected abstract void onIncomingCallEnded(Context ctx, String number, Date start, Date end);

    protected abstract void onOutgoingCallStarted(Context ctx, String number, Date start);      
    protected abstract void onOutgoingCallEnded(Context ctx, String number, Date start, Date end);

    protected abstract void onMissedCall(Context ctx, String number, Date start);

    //Deals with actual events

    //Incoming call-  goes from IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when its hung up
    //Outgoing call-  goes from IDLE to OFFHOOK when it dials out, to IDLE when hung up
    public void onCallStateChanged(Context context, int state, String number) {
        if(lastState == state){
            //No change, debounce extras
            return;
        }
        switch (state) {
            case TelephonyManager.CALL_STATE_RINGING:
                isIncoming = true;
                callStartTime = new Date();
                savedNumber = number;
                onIncomingCallReceived(context, number, callStartTime);
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                //Transition of ringing->offhook are pickups of incoming calls.  Nothing done on them
                if(lastState != TelephonyManager.CALL_STATE_RINGING){
                    isIncoming = false;
                    callStartTime = new Date();
                    onOutgoingCallStarted(context, savedNumber, callStartTime);                     
                }
                else
                {
                    isIncoming = true;
                    callStartTime = new Date();
                    onIncomingCallAnswered(context, savedNumber, callStartTime); 
                }

                break;
            case TelephonyManager.CALL_STATE_IDLE:
                //Went to idle-  this is the end of a call.  What type depends on previous state(s)
                if(lastState == TelephonyManager.CALL_STATE_RINGING){
                    //Ring but no pickup-  a miss
                    onMissedCall(context, savedNumber, callStartTime);
                }
                else if(isIncoming){
                    onIncomingCallEnded(context, savedNumber, callStartTime, new Date());                       
                }
                else{
                    onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());                                               
                }
                break;
        }
        lastState = state;
    }
}

তারপরে এটি ব্যবহার করার জন্য, কেবল এ থেকে কোনও শ্রেণি নেওয়া এবং কয়েকটি সহজ ফাংশন বাস্তবায়ন করুন, যে কোনও কল টাইপের ক্ষেত্রে আপনি যত্নশীল:

public class CallReceiver extends PhonecallReceiver {

    @Override
    protected void onIncomingCallReceived(Context ctx, String number, Date start)
    {
        //
    }

    @Override
    protected void onIncomingCallAnswered(Context ctx, String number, Date start)
    {
        //
    }

    @Override
    protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end)
    {
        //
    }

    @Override
    protected void onOutgoingCallStarted(Context ctx, String number, Date start)
    {
        //
    } 

    @Override 
    protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end)
    {
        //
    }

    @Override
    protected void onMissedCall(Context ctx, String number, Date start)
    {
        //
    }

}

এছাড়াও আপনি একটি লিখনআপ দেখতে পাচ্ছেন যে কোডটি আমার ব্লগে যেমন রয়েছে কেন সেটার জন্য আমি করেছি । সংক্ষিপ্ত লিঙ্ক: https://gist.github.com/ftvs/e61ccb039f511eb288ee

সম্পাদনা: সহজ কোডে আপডেট হয়েছে, আমি নিজের ব্যবহারের জন্য ক্লাসটি পুনরায় তৈরি করেছি


2
এই কোড কিছুই প্রদর্শন করে না। এটি যা করে তা আপনাকে কল করে যখন কোনও বহির্গামী কল শুরু / শেষ হয় এবং আপনাকে নম্বর, সময় শুরু এবং সময় শেষ করে দেয়। আসলে এটি প্রদর্শন করা আপনার কাজ, কারণ আপনি কীভাবে এটি করতে চান তা জানার আমার কোনও উপায় নেই।
গাব সেকান

3
@ গ্যাবেসচান: দুর্দান্ত! আপনি দয়া করে কল-অপেক্ষার পরিস্থিতি পরিচালনা করতে আমাকে গাইড করতে পারেন?
মেহুল জোছার

6
কেবল এটি যুক্ত করতে, অ্যাপটি অগ্রভাগ বা ব্যাকগ্রাউন্ডে না থাকলে এটি কাজ করে না যতক্ষণ না আমি এটি রিসিভারে যোগ না করে: "অ্যান্ড্রয়েড: সক্ষম =" সত্য "
রজত শর্মা

1
অ্যাপ্লিকেশনটিকে মেমরি থেকে সরিয়ে না দেওয়া পর্যন্ত স্ট্যাটিক ভেরিয়েবলগুলি প্রায় থাকবে (যা পরিষেবাগুলি চলছে এবং সাধারণ ফোনের মেমরির অবস্থার উপর নির্ভর করে যা বেশ দীর্ঘ সময় হতে পারে)। তবে হ্যাঁ, তারা হারিয়ে যেতে পারে। আপনি এটি ডিস্কে লিখতে পারেন, ভাগ করে নেওয়া পছন্দ হিসাবে বলুন তবে এটি আপনাকে ভুল ফলাফলও হতে পারে- এটি আপনাকে বেশ কয়েকটি ক্ষেত্রে যেমন আপনার ফোন সঠিকভাবে সাফ করা থেকে বিরত করবে যেমন ফোন রিবুটের আশপাশে। আমার ব্যবহারের ক্ষেত্রে বিরল নাল এবং হারানো ডেটা ভুল ডেটার চেয়ে ভাল ছিল। আপনার প্রয়োজন অনুসারে এলোমেলো মনে করুন।
গাবে স্যাচান

1
@ গ্যাবেসচান: এতে একটি বাগ রয়েছে বলে মনে হচ্ছে। lastState এটিকে আরম্ভ করা উচিত নয় CALL_STATE_IDLE। আমি কয়েকটা ফোন অনুপস্থিত করছি যখন আমার অ্যাপ্লিকেশন নিহত পরার সময় বর্তমান রাষ্ট্র RINGING। কারণ এটি যখন IDLEআবার কল শেষ হয় তখন স্থিতিশীল ভেরিয়েবলটি পুনরায় আরম্ভ করা হয় CALL_STATE_IDLEএবং এটি কিছুই না করে আত্মপ্রকাশ করে। সুতরাং আমরা রেফারেন্স হারাতে lastState
হাইজেনবার্গ

23
private MyPhoneStateListener phoneStateListener = new MyPhoneStateListener();

নিবন্ধন করতে

TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);

এবং নিবন্ধন করা

TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);

সর্বাধিক কর্মক্ষমতায় আমি এটি কোথায় ব্যবহার করব?
জেসবিন এমজে

ক্লাসে এটি রাখুন যেখানে আপনি পরিবর্তনটি শুনছেন .. সাধারণভাবে অনস্ক্রেট এবং অনডেস্ট্রয়ে নিবন্ধন করা হয় .. ক্লাসে বিশ্বব্যাপী অবজেক্টটি ঘোষণা করুন
স্টেইনপাইক

এই বিকল্পের অনুমতির প্রয়োজন নেই।
মাইক 14

যদিও গাবের দ্রবণটি আরও অনুপ্রবেশকারী বৈশিষ্ট্যগুলির জন্য যেমন ভাইবারের ধরণের অ্যাপ্লিকেশনগুলির জন্য আরও ভাল ফিট হয় তবে ফোন কলয়ে যাওয়ার ব্যবহারকারীর ক্রিয়া সম্পর্কে কেবল প্রতিক্রিয়া জানানো প্রয়োজন তাদের জন্য এটি সেরা সমাধান। এই জাতীয় ক্ষেত্রে রানটাইম অনুমতিের জন্য অনুরোধ করা সম্ভবত একটি ওভারকিল এবং সম্ভবত ব্যবহারকারী দ্বারা ভালভাবে গ্রহণ না করা হতে পারে।
2:52 তে বাইস্ফিয়ারে

1
আমি কিছু করতে চাই, যখন কল আসছে, এই কোডটি কীভাবে করবেন?
নূর হোসেন

14

অ্যান্ড্রয়েড পি - এপি স্তরের 28 সহ: আপনাকে READ_CALL_LOG অনুমতি নেওয়া দরকার

কল লগে অ্যাক্সেস সীমাবদ্ধ

অ্যান্ড্রয়েড পি চলে আসে CALL_LOG, READ_CALL_LOG, WRITE_CALL_LOG, এবং PROCESS_OUTGOING_CALLSথেকে অনুমতি PHONEনতুন করার অনুমতি গ্রুপ CALL_LOGঅনুমতি গ্রুপ। এই গোষ্ঠীটি ব্যবহারকারীদের ফোন কল সম্পর্কিত সংবেদনশীল তথ্যে যেমন ফোন কল রেকর্ড পড়া এবং ফোন নম্বর সনাক্তকরণের প্রয়োজন হয় এমন অ্যাপ্লিকেশনগুলিকে আরও ভাল নিয়ন্ত্রণ এবং দৃশ্যমানতা দেয়।

PHONE_STATE অভিপ্রায় কর্ম থেকে নম্বর পড়তে, আপনি উভয় প্রয়োজন READ_CALL_LOGঅনুমতি এবং READ_PHONE_STATEঅনুমতি । এর থেকে সংখ্যাগুলি পড়তে onCallStateChanged()আপনার এখন READ_CALL_LOGকেবল অনুমতি দরকার । আপনার আর READ_PHONE_STATEঅনুমতি লাগবে না ।


যারা কেবলমাত্র একটি অনুমতি অনুরোধ যোগ করার উপর ফোকাস যোগ করা READ_CALL_LOGহয় তাদের জন্য । AndroidManifest.xmlMainActivity
পীযূষ

13

আপডেট: গ্যাবে সেকান পোস্ট করা সত্যিই দুর্দান্ত কোডটি আর কাজ করে না আপনি যদি না ব্যবহারকারীকে প্রয়োজনীয় অনুমতি প্রদানের জন্য স্পষ্টভাবে অনুরোধ করেন। এখানে কিছু কোড রয়েছে যা আপনি এই অনুমতিগুলির জন্য অনুরোধ করতে আপনার মূল ক্রিয়াকলাপে রাখতে পারেন:

    if (getApplicationContext().checkSelfPermission(Manifest.permission.READ_PHONE_STATE)
            != PackageManager.PERMISSION_GRANTED) {
        // Permission has not been granted, therefore prompt the user to grant permission
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.READ_PHONE_STATE},
                MY_PERMISSIONS_REQUEST_READ_PHONE_STATE);
    }

    if (getApplicationContext().checkSelfPermission(Manifest.permission.PROCESS_OUTGOING_CALLS)
            != PackageManager.PERMISSION_GRANTED) {
        // Permission has not been granted, therefore prompt the user to grant permission
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.PROCESS_OUTGOING_CALLS},
                MY_PERMISSIONS_REQUEST_PROCESS_OUTGOING_CALLS);
    }

ALSO: যেমন কেউ গ্যাবের পোস্টের নীচে একটি মন্তব্যে উল্লিখিত হয়েছে android:enabled="true, অ্যাপ্লিকেশনটি বর্তমানে পূর্বেরগ্রাউন্ডে চলছে না এমন সময়ে আগত কলগুলি সনাক্ত করতে আপনাকে কোডের একটি সামান্য স্নিপেট যুক্ত করতে হবে :

    <!--This part is inside the application-->
    <receiver android:name=".CallReceiver" android:enabled="true">
        <intent-filter>
            <action android:name="android.intent.action.PHONE_STATE" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
        </intent-filter>
    </receiver>

যদি অ্যাপ্লিকেশনটির কোনও ক্রিয়াকলাপ না থাকে এবং কেবল ব্রডকাস্ট্রেসিভার এবং কোনও পরিষেবা না থাকে তবে কী হবে। তারপরে আমরা এই কোডটি কোথায় ব্যবহারকারীর কাছ থেকে অনুমতি পাওয়ার জন্য লিখি কারণ এই অনুমতি না দেওয়া পর্যন্ত ব্রডকাস্টারসিভারটি কল করা হবে না।
ব্যবহারকারী2779311

2
আপনার কেবলমাত্র একবার মুখ্য কার্যকলাপ প্রয়োজন তবে তা কেবল একবার খোলার পরেও। উদাহরণস্বরূপ আমার কল ব্লকিং অ্যাপটি রোবসটপ নিন: ব্যবহারকারী যখন প্রথমবার অ্যাপটি ডাউনলোড করে এবং তারপরে অ্যাপ্লিকেশনটি চালু করতে অ্যাপ্লিকেশন আইকনে ক্লিক করে, তখন তারা আমার অ্যাপ্লিকেশনটিকে প্রয়োজনীয় অনুমতিগুলি দেওয়ার জন্য অনুরোধ জানানো হয়। অ্যাপ্লিকেশনটিতে কল ব্লকিং সক্ষম / অক্ষম করার জন্য একটি বোতামও রয়েছে, তবে ব্যবহারকারীকে আবার অ্যাপ / ক্রিয়াকলাপ চালু করতে হবে না, কল অ্যাপ্লিকেশনটিকে অ্যাপ্লিকেশন / ক্রিয়াকলাপটি আরম্ভ না করে ব্যাকগ্রাউন্ডে স্থান দেওয়া হবে।
টোফারপেডারসন

যাঁদের এটি বাস্তবায়নে সমস্যা রয়েছে, তারা এই টিউটোরিয়ালটি স্টাডিটোরিয়াল
..

5

এটি আপনাকে সহায়তা করতে পারে এবং অনুমতিও লাগবে add

public class PhoneListener extends PhoneStateListener
{
    private Context context;
    public static String getincomno;

    public PhoneListener(Context c) {
        Log.i("CallRecorder", "PhoneListener constructor");
        context = c;
    }

    public void onCallStateChanged (int state, String incomingNumber)
    {

        if(!TextUtils.isEmpty(incomingNumber)){
        // here for Outgoing number make null to get incoming number
        CallBroadcastReceiver.numberToCall = null;
        getincomno = incomingNumber;
        }

        switch (state) {
        case TelephonyManager.CALL_STATE_IDLE:

            break;
        case TelephonyManager.CALL_STATE_RINGING:
            Log.d("CallRecorder", "CALL_STATE_RINGING");
            break;
        case TelephonyManager.CALL_STATE_OFFHOOK:

            break;
        }
    }
}

2
এটা ঠিক আছে বলে মনে হচ্ছে। তবে আমি কীভাবে এটি কার্যকলাপ থেকে ব্যবহার করতে পারি? দয়া করে আমাকে বিশদটি বলুন
আমির

4

শুধু গ্যাবে সেকানের উত্তর আপডেট করতে update আপনার ম্যানিফেস্ট READ_CALL_LOG এবং READ_PHONE_STATE করার অনুমতি জন্য অনুরোধ পারেন, onReceive নামক হবে দুইবার । যার একটিতে এতে EXTRA_INCOMING_NUMBER রয়েছে এবং অন্যটিতে তা নেই। আপনাকে যা পরীক্ষা করতে হবে এটি কোনটি ক্রমে ঘটতে পারে can

https://developer.android.com/reference/android/telephony/TelephonyManager.html#ACTION_PHONE_STATE_CHANGED


2

এখানে একটি সহজ পদ্ধতি যা ব্যবহার PhonestateListenerএবং অন্যান্য জটিলতা এড়াতে পারে ।
সুতরাং এখানে আমরা অ্যান্ড্রয়েড থেকে 3 টি ইভেন্ট যেমন RINGING, OFFHOOKএবং IDLE। শৃঙ্খলা কলের সব সম্ভব রাষ্ট্র পেতে, আমরা আমাদের নিজের রাজ্যের পছন্দ সংজ্ঞায়িত করতে প্রয়োজন RINGING, OFFHOOK, IDLE, FIRST_CALL_RINGING, SECOND_CALL_RINGING। এটি একটি ফোন কলে প্রতিটি রাজ্য পরিচালনা করতে পারে।
দয়া করে এমনভাবে ভাবুন যাতে আমরা অ্যান্ড্রয়েড থেকে ইভেন্টগুলি পাই এবং আমরা আমাদের কল স্টেটগুলি সংজ্ঞায়িত করব। কোড দেখুন।

public class CallListening  extends BroadcastReceiver {
    private static final String TAG ="broadcast_intent";
    public static String incoming_number;
    private String current_state,previus_state,event;
    public static Boolean dialog= false;
    private Context context;
    private SharedPreferences sp,sp1;
    private SharedPreferences.Editor spEditor,spEditor1;
    public void onReceive(Context context, Intent intent) {
        //Log.d("intent_log", "Intent" + intent);
        dialog=true;
        this.context = context;
        event = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
        incoming_number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
        Log.d(TAG, "The received event : "+event+", incoming_number : " + incoming_number);
        previus_state = getCallState(context);
        current_state = "IDLE";
        if(incoming_number!=null){
            updateIncomingNumber(incoming_number,context);
        }else {
            incoming_number=getIncomingNumber(context);
        }
        switch (event) {
            case "RINGING":
                Log.d(TAG, "State : Ringing, incoming_number : " + incoming_number);
            if((previus_state.equals("IDLE")) || (previus_state.equals("FIRST_CALL_RINGING"))){
                    current_state ="FIRST_CALL_RINGING";
                }
                if((previus_state.equals("OFFHOOK"))||(previus_state.equals("SECOND_CALL_RINGING"))){
                    current_state = "SECOND_CALL_RINGING";
                }

                break;
            case "OFFHOOK":
                Log.d(TAG, "State : offhook, incoming_number : " + incoming_number);
                if((previus_state.equals("IDLE")) ||(previus_state.equals("FIRST_CALL_RINGING")) || previus_state.equals("OFFHOOK")){
                    current_state = "OFFHOOK";
                }
                if(previus_state.equals("SECOND_CALL_RINGING")){
                    current_state ="OFFHOOK";
                    startDialog(context);
                }
                break;
            case "IDLE":
                Log.d(TAG, "State : idle and  incoming_number : " + incoming_number);
                if((previus_state.equals("OFFHOOK")) || (previus_state.equals("SECOND_CALL_RINGING")) || (previus_state.equals("IDLE"))){
                    current_state="IDLE";
                }
                if(previus_state.equals("FIRST_CALL_RINGING")){
                    current_state = "IDLE";
                    startDialog(context);
                }
                updateIncomingNumber("no_number",context);
                Log.d(TAG,"stored incoming number flushed");
                break;
        }
        if(!current_state.equals(previus_state)){
            Log.d(TAG, "Updating  state from "+previus_state +" to "+current_state);
            updateCallState(current_state,context);

        }
    }
    public void startDialog(Context context) {
        Log.d(TAG,"Starting Dialog box");
        Intent intent1 = new Intent(context, NotifyHangup.class);
        intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent1);

    }
    public void updateCallState(String state,Context context){
        sp = PreferenceManager.getDefaultSharedPreferences(context);
        spEditor = sp.edit();
        spEditor.putString("call_state", state);
        spEditor.commit();
        Log.d(TAG, "state updated");

    }
    public void updateIncomingNumber(String inc_num,Context context){
        sp = PreferenceManager.getDefaultSharedPreferences(context);
        spEditor = sp.edit();
        spEditor.putString("inc_num", inc_num);
        spEditor.commit();
        Log.d(TAG, "incoming number updated");
    }
    public String getCallState(Context context){
        sp1 = PreferenceManager.getDefaultSharedPreferences(context);
        String st =sp1.getString("call_state", "IDLE");
        Log.d(TAG,"get previous state as :"+st);
        return st;
    }
    public String getIncomingNumber(Context context){
        sp1 = PreferenceManager.getDefaultSharedPreferences(context);
        String st =sp1.getString("inc_num", "no_num");
        Log.d(TAG,"get incoming number as :"+st);
        return st;
    }
}

0

@ গ্যাবে সেকান, আপনার কোডের জন্য ধন্যবাদ এটা তোলে ব্যতীত কাজ করে জরিমানা onOutgoingCallEnded()। এটি কখনই কার্যকর করা হয় না। টেস্টিং ফোনগুলি হ'ল স্যামসাং এস 5 এবং ট্রেন্ডি। আমি মনে করি 2 টি বাগ আছে।

1: এক জোড়া বন্ধনী অনুপস্থিত।

case TelephonyManager.CALL_STATE_IDLE: 
    // Went to idle-  this is the end of a call.  What type depends on previous state(s)
    if (lastState == TelephonyManager.CALL_STATE_RINGING) {
        // Ring but no pickup-  a miss
        onMissedCall(context, savedNumber, callStartTime);
    } else {
        // this one is missing
        if(isIncoming){
            onIncomingCallEnded(context, savedNumber, callStartTime, new Date());                       
        } else {
            onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());                                               
        }
    }
    // this one is missing
    break;

2: এটি ফাংশনের শেষে থাকলে lastStateআপডেট হয় না state। এটি দ্বারা এই ফাংশনের প্রথম লাইনে প্রতিস্থাপন করা উচিত

public void onCallStateChanged(Context context, int state, String number) {
    int lastStateTemp = lastState;
    lastState = state;
    // todo replace all the "lastState" by lastStateTemp from here.
    if (lastStateTemp  == state) {
        //No change, debounce extras
        return;
    }
    //....
}

অতিরিক্ত আমি রেখেছি lastStateএবং savedNumberভাগ পক্ষপাত মধ্যে হিসাবে আপনি সুপারিশ করেছে।

উপরোক্ত পরিবর্তনগুলি সহ এটি কেবল পরীক্ষা করা হয়েছে। কমপক্ষে আমার ফোনে বাগ ঠিক করা হয়েছে।


0

দয়া করে নীচের কোডটি ব্যবহার করুন। এটি আপনাকে অন্যান্য কলের বিশদ সহ আগত নম্বর পেতে সহায়তা করবে।

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >

<TextView
    android:id="@+id/call"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:text="@string/hello_world" />

</RelativeLayout>

MainActivity.java

public class MainActivity extends Activity {

private static final int MISSED_CALL_TYPE = 0;
private TextView txtcall;

@Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    txtcall = (TextView) findViewById(R.id.call);

    StringBuffer sb = new StringBuffer();
    Cursor managedCursor = managedQuery(CallLog.Calls.CONTENT_URI, null,
            null, null, null);
    int number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER);
    int type = managedCursor.getColumnIndex(CallLog.Calls.TYPE);
    int date = managedCursor.getColumnIndex(CallLog.Calls.DATE);
    int duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION);
    sb.append("Call Details :");
    while (managedCursor.moveToNext()) {
        String phNumber = managedCursor.getString(number);
        String callType = managedCursor.getString(type);
        String callDate = managedCursor.getString(date);
        Date callDayTime = new Date(Long.valueOf(callDate));
        String callDuration = managedCursor.getString(duration);
        String dir = null;
        int dircode = Integer.parseInt(callType);
        switch (dircode) {

        case CallLog.Calls.OUTGOING_TYPE:
            dir = "OUTGOING";
            break;

        case CallLog.Calls.INCOMING_TYPE:
            dir = "INCOMING";
            break;

        case CallLog.Calls.MISSED_TYPE:
            dir = "MISSED";
            break;
        }
        sb.append("\nPhone Number:--- " + phNumber + " \nCall Type:--- "
                + dir + " \nCall Date:--- " + callDayTime
                + " \nCall duration in sec :--- " + callDuration);
        sb.append("\n----------------------------------");
    }
    managedCursor.close();
    txtcall.setText(sb);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

} 

এবং নিম্নলিখিত অনুমতিগুলির জন্য আপনার প্রকাশিত অনুরোধে:

<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.READ_LOGS"/>

READ_LOGS এটি করছে যাতে আপনার অ্যাপ্লিকেশনটি প্লে স্টোর থেকে নিষিদ্ধ করা হয়
ডুনা

0

আপনার জন্য একটি ব্রডকাস্টার ACTION_PHONE_STATE_CHANGEDরিসিভার দরকার এটি যখনই ফোন-স্টেটটি নিষ্ক্রিয়, রিং করা, অফহুক থেকে পূর্বের মান থেকে পরিবর্তন করে এবং আপনি যে নতুন মানটি ইনকামিং / আউটগোয়িং কল কিনা তা সনাক্ত করতে পারেন তার থেকে পরিবর্তিত হবে।

প্রয়োজনীয় অনুমতি হবে:

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

তবে আপনিও যদি সেই সম্প্রচারে EXTRA_INCOMING_NUMBER পেতে চান তবে আপনার আর একটি অনুমতি প্রয়োজন হবে: "android.permission.READ_CALL_LOG"

এবং কোডটি এরকম কিছু:

val receiver: BroadcastReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        Log.d(TAG, "onReceive")
    }
}

override fun onResume() {
    val filter = IntentFilter()
    filter.addAction("android.intent.action.PHONE_STATE")
    registerReceiver(receiver, filter)
    super.onResume()
}

override fun onPause() {
    unregisterReceiver(receiver)
    super.onPause()
}

এবং রিসিভার ক্লাসে আমরা এই জাতীয় উদ্দেশ্য পাঠ করে বর্তমান অবস্থা পেতে পারি:

intent.extras["state"]

অতিরিক্ত ফলাফল হতে পারে:

রিং করা হচ্ছে -> আপনার ফোনটি বেজে উঠছে

অফফুক -> আপনি যদি কারও সাথে কথা বলছেন (আগত বা আগত কল)

আইডিএল -> কল শেষ হলে (আগত বা আগত কল)

PHONE_STATE সম্প্রচারের সাথে আমাদের PROCESS_OUTGOING_CALLS অনুমতি বা প্রত্যাখ্যান করা NEW_OUTGOING_CALL ক্রিয়া ব্যবহার করার দরকার নেই।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.