Android'de telefon araması nasıl yapılır ve arama bittiğinde aktiviteme nasıl geri dönerim?


129

Bir telefon görüşmesi yapmak için bir etkinlik başlatıyorum, ancak 'aramayı sonlandır' düğmesine bastığımda faaliyetime geri dönmüyor. 'Aramayı sonlandır' düğmesine basıldığında bana geri gelen bir arama etkinliğini nasıl başlatabilirim? Telefon görüşmesini şu şekilde yapıyorum:

    String url = "tel:3334444";
    Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url));

Yanıtlar:


106

Aramanın ne zaman bittiğini görmek için bir PhoneStateListener kullanın. büyük olasılıkla bir aramanın başlamasını beklemek için dinleyici eylemlerini tetiklemeniz (tekrar PHONE_STATE_OFFHOOK'tan PHONE_STATE_IDLE olarak değiştirilene kadar bekleyin) ve ardından uygulamanızı IDLE durumuna geri getirmek için bir kod yazmanız gerekecektir.

Çalıştığından ve uygulamanızın yeniden başlatıldığından emin olmak için dinleyiciyi bir hizmette çalıştırmanız gerekebilir. bazı örnek kodlar:

EndCallListener callListener = new EndCallListener();
TelephonyManager mTM = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
mTM.listen(callListener, PhoneStateListener.LISTEN_CALL_STATE);

Dinleyici tanımı:

private class EndCallListener extends PhoneStateListener {
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        if(TelephonyManager.CALL_STATE_RINGING == state) {
            Log.i(LOG_TAG, "RINGING, number: " + incomingNumber);
        }
        if(TelephonyManager.CALL_STATE_OFFHOOK == state) {
            //wait for phone to go offhook (probably set a boolean flag) so you know your app initiated the call.
            Log.i(LOG_TAG, "OFFHOOK");
        }
        if(TelephonyManager.CALL_STATE_IDLE == state) {
            //when this state occurs, and your flag is set, restart your app
            Log.i(LOG_TAG, "IDLE");
        }
    }
}

Sizin de Manifest.xmldosyaya aşağıdaki iznini ekleyin:

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

10
İzni unutma. ;)
Gp2mv3

5
Gp2mv3'ün de belirttiği gibi, AndroidManifest.xml'e READ_PHONE_STATE iznini eklemeyi unutmayın.
Cooper

6
@moonlightcheese Çağrı uygulamasından uygulamamıza geri dönmek için kod ekleyebilir misiniz?
Geek

bu tehlikelidir çünkü her aradığınızda uygulama etkinliğinizi her zaman
açacaktır

49

Bu, Starter'ın sorduğu soruyla ilgilidir.

Kodunuzla ilgili sorun, numarayı düzgün bir şekilde geçirememenizdir.

Kod şu şekilde olmalıdır:

private OnClickListener next = new OnClickListener() {

     public void onClick(View v) {
        EditText num=(EditText)findViewById(R.id.EditText01); 
        String number = "tel:" + num.getText().toString().trim();
        Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse(number)); 
        startActivity(callIntent);
    }
};

Manifest dosyasına izni eklemeyi unutmayınız.

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

veya

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

Acil durum numarası DIALiçin kullanılması durumunda .


7
Kodunuzun orijinal sorudaki koddan ne kadar farklı olduğunu
görmekte zorlanıyorum

Kod farklı değil. Manifest dosyasına izni eklemeniz gerekiyor.
Pria

4
android.permission.CALL_PRIVILEGED İzin, yalnızca uygulama düzeyinde mevcut olmayan sistem uygulamalarına verilir.
CoDe

ve bu nedir? etkinliğinize geri dönmeyecek
user924

24

Aynı sorunu yaşadık ve PhoneStateListeneraramanın ne zaman bittiğini belirlemek için a kullanarak çözmeyi başardık , ancak ek olarak finish()tekrar başlatmadan önce orijinal etkinliğe sahip olmamız gerekiyordu startActivity, aksi takdirde arama kaydı önünde olurdu.


4
farklı bir yöntem kullanarak bunu önleyebilirsiniz. Android arama günlüğünü gözlemleyen bir ContentObserver oluşturursanız, arama günlüğü değişikliği yapılana kadar uygulama başlamaz. Aslında PhoneStateListener'ı bu modelin lehine dökmek zorunda kaldım, çünkü uygulamam çağrı günlüğü verilerine ihtiyaç duyuyordu ve dinleyici bu değişiklikler yapılmadan önce geri dönüyordu. pastebin.com/bq2s9EVa
moonlightcheese

11
@ André: Bağlantınız bozuk görünüyor
aggregate1166877

Sana bir milyon itibar verirdim (eğer çok şey olsaydı :)) Günümü yaptığınız için teşekkürler!
keybee

1
Bağlantılarla ilgili sorun diyorum!
Dheeraj Bhaskar


13

Tanımlanan davranışı elde etmek için EndCallListener'ı en işlevsel örnek olarak buldum (finish (), call, restart) Birkaç SharedPreferences ekledim, böylece Listener bu davranışı yönetmek için bir referansa sahip oldu.

My OnClick, initialise ve EndCallListener yalnızca uygulamadan gelen çağrılara yanıt verir. Diğer çağrılar göz ardı edildi.

import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;

public class EndCallListener extends PhoneStateListener {

private String TAG ="EndCallListener";
private int     LAUNCHED = -1;

SharedPreferences prefs = PreferenceManager
                            .getDefaultSharedPreferences(
                                myActivity.mApp.getBaseContext());

SharedPreferences.Editor _ed = prefs.edit();

@Override
    public void onCallStateChanged(int state, String incomingNumber) {
    String _prefKey = myActivity.mApp                          
                      .getResources().getString(R.string.last_phone_call_state_key),
    _bPartyNumber = myActivity.mApp                           
                      .getResources().getString(R.string.last_phone_call_bparty_key);

    int mLastCallState = prefs.getInt(_prefKey, LAUNCHED);

    //Save current call sate for next call
    _ed.putInt(_prefKey,state);
    _ed.commit();

        if(TelephonyManager.CALL_STATE_RINGING == state) {
            Log.i(TAG, " >> RINGING, number: " + incomingNumber);
        }
        if(TelephonyManager.CALL_STATE_IDLE == state && mLastCallState != LAUNCHED ) {
            //when this state occurs, and your flag is set, restart your app

            if (incomingNumber.equals(_bPartyNumber) == true) {
                //Call relates to last app initiated call
            Intent  _startMyActivity =  
               myActivity.mApp                               
               .getPackageManager()                                  
               .getLaunchIntentForPackage(
                 myActivity.mApp.getResources()
                 .getString(R.string.figjam_package_path));

_startMyActivity.setAction(                                     
        myActivity.mApp.getResources()
        .getString(R.string.main_show_phone_call_list));

                myActivity.mApp
                        .startActivity(_startMyActivity);
                Log.i(TAG, "IDLE >> Starting MyActivity with intent");
            }
            else
                Log.i(TAG, "IDLE after calling "+incomingNumber);

        }

    }
}

bunları strings.xml dosyasına ekleyin

<string name="main_show_phone_call_list">android.intent.action.SHOW_PHONE_CALL_LIST</string>
<string name="last_phone_call_state_key">activityLpcsKey</string>
<string name="last_phone_call_bparty_key">activityLpbpKey</string>

ve aramadan önceki görünüm ve izlenime geri dönmeniz gerekirse Manifest'inizde buna benzer bir şey

  <activity android:label="@string/app_name" android:name="com.myPackage.myActivity" 
      android:windowSoftInputMode="stateHidden"
        android:configChanges="keyboardHidden" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <action android:name="android.intent.action.SHOW_PHONE_CALL_LIST" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
  </activity>

ve bunları "Etkinliğim" e koyun

public static Activity mApp=null; //Before onCreate()
  ...
onCreate( ... ) {
  ...
if (mApp == null) mApp = this; //Links your resources to other classes
  ...
    //Test if we've been called to show phone call list
    Intent _outcome = getIntent();
    String _phoneCallAction = mApp.getResources().getString(R.string.main_show_phone_call_list);
    String _reqAction = _outcome.getAction();//Can be null when no intent involved

         //Decide if we return to the Phone Call List view
         if (_reqAction != null &&_reqAction.equals(_phoneCallAction) == true) {
                         //DO something to return to look and feel
         }

  ...
        myListView.setOnItemClickListener(new OnItemClickListener() { //Act on item when selected
             @Override
             public void onItemClick(AdapterView<?> a, View v, int position, long id) {

                 myListView.moveToPosition(position);
                 String _bPartyNumber = "tel:"+myListView.getString(myListView.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); 

                 //Provide an initial state for the listener to access.
                 initialiseCallStatePreferences(_bPartyNumber);

                 //Setup the listener so we can restart myActivity
                    EndCallListener _callListener = new EndCallListener();
                    TelephonyManager _TM = (TelephonyManager)mApp.getSystemService(Context.TELEPHONY_SERVICE);

                    _TM.listen(_callListener, PhoneStateListener.LISTEN_CALL_STATE);

                         Intent _makeCall = new Intent(Intent.ACTION_CALL, Uri.parse(_bPartyNumber));

                 _makeCall.setComponent(new ComponentName("com.android.phone","com.android.phone.OutgoingCallBroadcaster"));
                    startActivity(_makeCall);                           
                finish();
              //Wait for call to enter the IDLE state and then we will be recalled by _callListener
              }
        });


}//end of onCreate()

bunu myActivity'de onClick'inizin davranışını başlatmak için kullanın, örneğin onCreate () sonrasında

private void initialiseCallStatePreferences(String _BParty) {
    final int LAUNCHED = -1;
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(
                                mApp.getBaseContext());
    SharedPreferences.Editor _ed = prefs.edit();

    String _prefKey = mApp.getString(R.string.last_phone_call_state_key),
           _bPartyKey = mApp.getString(R.string.last_phone_call_bparty_key);

    //Save default call state before next call
        _ed.putInt(_prefKey,LAUNCHED);
        _ed.putString(_bPartyKey,_BParty);
        _ed.commit();

}

Telefon numaraları listenize tıklamanın etkinliğinizi bitirdiğini, numarayı aradığını ve arama bittiğinde etkinliğinize geri döndüğünü görmelisiniz.

Hala etrafta iken uygulamanızın dışından bir arama yapmak, etkinliğinizi yeniden başlatmaz (aranan son BParty numarasıyla aynı olmadığı sürece).

:)


5
Üzgünüm ama bu kod biraz çirkin görünüyor. Cevabınız için teşekkürler
Pierre

7

startActivityForResult () kullanabilirsiniz


1
Android 5.0 kullanıldığında, onActivityResult yöntemi çağrı hemen başlar!
Panciz

6

Bu benim bakış açıma göre çözüm:

ok.setOnClickListener(this);
@Override
public void onClick(View view) {
    if(view == ok){
        Intent intent = new Intent(Intent.ACTION_CALL);
        intent.setData(Uri.parse("tel:" + num));
        activity.startActivity(intent);

    }

Tabii ki Activity (sınıf) tanımında View.OnClickListener uygulamanız gerekir.


6

İşte benim örneğim, önce kullanıcı çevirmek istediği numarayı yazıyor ve ardından bir arama düğmesine basıp telefona yönlendiriliyor. Çağrı iptalinden sonra kullanıcı uygulamaya geri gönderilir. Bunun için düğmenin xml'de bir onClick yöntemine (bu örnekte 'makePhoneCall') sahip olması gerekir. Ayrıca izni manifest'e kaydetmeniz gerekir.

Belirgin

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

Aktivite

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class PhoneCall extends Activity {

    EditText phoneTo;

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

        phoneTo = (EditText) findViewById(R.id.phoneNumber);

    }
    public void makePhoneCall(View view) {




        try {
            String number = phoneTo.getText().toString();
            Intent phoneIntent = new Intent(Intent.ACTION_CALL);
            phoneIntent.setData(Uri.parse("tel:"+ number));
            startActivity(phoneIntent);


        } catch (android.content.ActivityNotFoundException ex) {
            Toast.makeText(PhoneCall.this,
                    "Call failed, please try again later!", Toast.LENGTH_SHORT).show();
        }
    }

}

XML

 <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inputType="phone"
        android:ems="10"
        android:id="@+id/phoneNumber"
        android:layout_marginTop="67dp"
        android:layout_below="@+id/textView"
        android:layout_centerHorizontal="true" />

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Call"
        android:id="@+id/makePhoneCall"
        android:onClick="makePhoneCall"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true" />

ne hakkında konuştuğunu bile bilmiyorsun. READ_PHONE_STATE - örnek kodunuzda kullanmıyorsunuz, neden eklediniz? Tabii ki iptal düğmesine basarsanız sizi uygulama etkinliğinize geri döndürecektir, ancak sorunun yazarı çağrı kabul edildikten sonra etkinliğe nasıl geri
dönüleceğini sordu

6
@Override
public void onClick(View view) {
    Intent phoneIntent = new Intent(Intent.ACTION_CALL);
    phoneIntent.setData(Uri.parse("tel:91-000-000-0000"));
    if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    startActivity(phoneIntent);
}

5

Bir dinleyici kullanacaksanız, bu izni manifestoya da eklemeniz gerekecektir.

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

3

PhoneStateListener içinde aramanın bittiğini gördükten sonra daha iyi kullanın:

Intent intent = new Intent(CallDispatcherActivity.this, CallDispatcherActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

CallDispatcherActivity, kullanıcının bir arama başlattığı etkinliktir (benim durumumda bir taksi hizmeti memuruna). Bu sadece Android telefon uygulamasını yukarıdan kaldırıyor, kullanıcı burada gördüğüm çirkin kod yerine geri dönüyor.


1
Ve telefon görüşmesi bittikten sonra şu şekilde dinleyiciyi kaldırmayı unutmayın:((TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE)).listen(this, LISTEN_NONE);
Dmitri Novikov

Yaklaşımınızı kullanmayı denedim, ancak etkinlik (Kontrol Paneli olarak adlandırılır) yeniden etkinleştirilmiyor. Ekran, telefon çevirici arayüzünü göstermeye devam eder ve ControlPanel içindeki onResume ve onNewIntent giriş noktalarındaki kaydediciler tamamen sessizdir. İşte niyet var: Intent intentRestart = new Intent(ControlPanel.this, ControlPanel.class);. PhoneStateListener'ın da ControlPanel içinde olduğunu belirtmeliyim. Yani, amacım kullanıcı arayüzünü telefon görüşmesini başlatmadan önceki durumuna geri yüklemek. Baska öneri?
PeteH

PhoneStateListener uygulamanızın içinde oturum açmayı deneyin.
Dmitri Novikov

3

Kendinize dönmek için Activity, dinlemeniz gerekecek TelephonyStates. Bunun üzerine , telefon boşta listenerkaldığında Intenttekrar açmak için Activitybir gönderebilirsin .

En azından ben böyle yapacağım.


3
  Intent callIntent = new Intent(Intent.ACTION_CALL);  
  callIntent.setData(Uri.parse("tel:"+number));  
   startActivity(callIntent);   

 **Add permission :**

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

2

Şunları kullanmayı deneyin:

finish();

faaliyetin sonunda. Sizi önceki etkinliğinize yönlendirecektir.


2

Ne zaman PhoneStateListenerkullanılır, tek ihtiyacı emin olmak için PHONE_STATE_IDLEbir aşağıdaki PHONE_STATE_OFFHOOKçağrısından sonra yapılacak işlemi tetikleme kullanılır. Tetikleme gördükten sonra olursa PHONE_STATE_IDLE, aramadan önce yapmaya başlayacaksınız. Çünkü devletin değiştiğini göreceksinPHONE_STATE_IDLE -> PHONE_STATE_OFFHOOK -> PHONE_STATE_IDLE.


Devam eden çağrı ekranı açıldığında uygulamanın durması mümkün değil mi?
lisovaccaro

Dinleyici nesnesi, TelephonyManager'ı dinlemeye ayarlandıktan ((TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE)).listen(new PhoneStateListener(), PhoneStateListener.LISTEN_CALL_STATE)sonra telefon durumunu dinlemeye devam edecek ve açıkça durdurulana kadar etkin kalacaktır((TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE)).listen(this, LISTEN_NONE)
PonMaran

2

// setonclicklistener'da şu kodu girin:

EditText et_number=(EditText)findViewById(R.id.id_of_edittext); 
String my_number = et_number.getText().toString().trim();
Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse(my_number)); 
startActivity(callIntent);

// bildirimde çağrı için izin verin:

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

1

@Dmitri Novikov, yenisinin FLAG_ACTIVITY_CLEAR_TOPüstündeki tüm aktif örnekleri temizler. Dolayısıyla, süreci tamamlamadan eski vakayı sonlandırabilir.



1

Adımlar:

1) Manifest.xmlDosyaya gerekli izinleri ekleyin .

<!--For using the phone calls -->
<uses-permission android:name="android.permission.CALL_PHONE" />
<!--For reading phone call state-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

2) Telefon durumu değişiklikleri için bir dinleyici oluşturun.

public class EndCallListener extends PhoneStateListener {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
    if(TelephonyManager.CALL_STATE_RINGING == state) {
    }
    if(TelephonyManager.CALL_STATE_OFFHOOK == state) {
        //wait for phone to go offhook (probably set a boolean flag) so you know your app initiated the call.
    }
    if(TelephonyManager.CALL_STATE_IDLE == state) {
        //when this state occurs, and your flag is set, restart your app
    Intent i = context.getPackageManager().getLaunchIntentForPackage(
                            context.getPackageName());
    //For resuming the application from the previous state
    i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

    //Uncomment the following if you want to restart the application instead of bring to front.
    //i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    context.startActivity(i);
    }
}
}

3) Listenizdeki dinleyiciyi başlatın. OnCreate

EndCallListener callListener = new EndCallListener();
TelephonyManager mTM = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
mTM.listen(callListener, PhoneStateListener.LISTEN_CALL_STATE);

ancak başvurunuzun son durumunu devam ettirmek için ya da arka arka yığınından getirmek istiyorsanız , o zaman değiştirin FLAG_ACTIVITY_CLEAR_TOPileFLAG_ACTIVITY_SINGLE_TOP

Bu Yanıtı referans alın



0

Aramanıza başlarken iyi görünüyor.

Yine de uygulamanızı öne çıkarırken android 11+ ile aşağı arasında bir fark var.

Yeni bir amaç başlatmanız gereken Android 10 veya daha az, yalnızca kullandığınız android 11+ BringTaskToFront

Çağrı durumunda IDLE:

if (Build.VERSION.SDK_INT >= 11) {
    ActivityManager am = (ActivityManager) activity.getSystemService(Activity.ACTIVITY_SERVICE);
    am.moveTaskToFront(MyActivity.MyActivityTaskId, ActivityManager.MOVE_TASK_WITH_HOME);
} else {
    Intent intent = new Intent(activity, MyActivity.class);
    activity.startActivity(intent);
}

MyActivity.MyActivityTaskIdEtkinliğimde arama yaparken öyle ayarlıyorum, bu işe yaramıyor, bu değişkeni geri dönmek istediğiniz sayfanın ana etkinlik sayfasından ayarlayın.

MyActivity.MyActivityTaskId = this.getTaskId();

MyActivityTaskId aktivite sınıfımdaki statik bir değişkendir

public static int MyActivityTaskId = 0;

Umarım bu sizin için işe yarar. Yukarıdaki kodu biraz farklı kullanıyorum, aramaya cevap verilir verilmez uygulamamı açıyorum, böylece kullanıcı arayanın detaylarını görebilsin.

Ben de bazı şeyler ayarladım AndroidManifest.xml:

/*Dont really know if this makes a difference*/
<activity android:name="MyActivity" android:taskAffinity="" android:launchMode="singleTask" />

ve izinler:

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

Lütfen takılıp kalırsanız veya ne zaman soru sorun.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.