Bagaimana cara membuat panggilan telepon di android dan kembali ke aktivitas saya ketika panggilan selesai?


129

Saya meluncurkan aktivitas untuk membuat panggilan telepon, tetapi ketika saya menekan tombol 'end call', itu tidak kembali ke aktivitas saya. Bisakah Anda memberi tahu saya bagaimana saya bisa memulai aktivitas panggilan yang kembali kepada saya ketika tombol 'End call' ditekan? Inilah cara saya melakukan panggilan telepon:

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

Jawaban:


106

gunakan PhoneStateListener untuk melihat kapan panggilan berakhir. Anda kemungkinan besar perlu memicu tindakan pendengar untuk menunggu panggilan dimulai (tunggu sampai diubah dari PHONE_STATE_OFFHOOK ke PHONE_STATE_IDLE lagi) dan kemudian menulis beberapa kode untuk mengembalikan aplikasi Anda pada status IDLE.

Anda mungkin perlu menjalankan pendengar dalam layanan untuk memastikannya tetap hidup dan aplikasi Anda dimulai kembali. beberapa kode contoh:

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

Definisi pendengar:

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

Di Manifest.xmlfile Anda tambahkan izin berikut:

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

10
Jangan lupa izinnya. ;)
Gp2mv3

5
Seperti yang dicatat oleh Gp2mv3, jangan lupa untuk menambahkan izin READ_PHONE_STATE ke AndroidManifest.xml.
Cooper

6
@moonlightcheese Bisakah Anda menambahkan kode untuk kembali ke aplikasi kami dari aplikasi panggilan?
Geek

ini berbahaya karena akan selalu membuka aktivitas aplikasi Anda setiap kali Anda menelepon
user924

49

Ini tentang pertanyaan yang diajukan oleh Pemula.

Masalah dengan kode Anda adalah Anda tidak memberikan nomor dengan benar.

Kode tersebut harus:

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

Jangan lupa untuk menambahkan izin dalam file manifes.

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

atau

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

untuk nomor darurat jika DIALdigunakan.


7
Saya mengalami kesulitan untuk melihat bagaimana kode Anda berbeda dari kode pada pertanyaan awal
Elijah Saounkine

Kode tidak berbeda. Anda perlu menambahkan izin dalam file manifes.
Pria

4
android.permission.CALL_PRIVILEGED Izin hanya diberikan untuk aplikasi sistem yang tidak tersedia di tingkat aplikasi.
CoDe

dan apa itu? itu tidak akan kembali ke aktivitas Anda
user924

24

Kami memiliki masalah yang sama dan berhasil menyelesaikannya dengan menggunakan a PhoneStateListeneruntuk mengidentifikasi kapan panggilan berakhir, tetapi selain itu kami harus ke finish()aktivitas asli sebelum memulai lagi dengan startActivity, jika tidak, log panggilan akan berada di depannya.


4
Anda dapat menghindari ini dengan menggunakan metode yang berbeda. jika Anda membuat ContentObserver yang mengamati log panggilan android, maka aplikasi tidak akan mulai sampai perubahan log panggilan dilakukan. saya benar-benar harus membuang PhoneStateListener yang mendukung model ini, karena aplikasi saya membutuhkan data log panggilan, dan pendengar kembali sebelum perubahan tersebut dibuat. pastebin.com/bq2s9EVa
moonlightcheese

11
@ André: tautan Anda tampaknya rusak
aggregate1166877

Saya akan memberi Anda sejuta reputasi (jika saya punya banyak :)) Terima kasih telah membuat hari saya!
keybee

1
Masalah dengan tautan saya katakan!
Dheeraj Bhaskar


13

Saya menemukan EndCallListener contoh paling fungsional, untuk mendapatkan perilaku yang dijelaskan (selesai (), panggilan, restart) saya menambahkan beberapa SharedPreferences sehingga Listener memiliki referensi untuk mengelola perilaku ini.

OnClick, inisialisasi, dan EndCallListener saya hanya merespons panggilan dari aplikasi. Panggilan lain diabaikan.

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

        }

    }
}

tambahkan ini ke strings.xml

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

dan sesuatu seperti ini dalam Manifes Anda jika Anda perlu kembali ke tampilan dan nuansa sebelum panggilan

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

dan letakkan ini di 'myActivity' Anda

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

gunakan ini untuk menginisialisasi perilaku untuk onClick Anda di myActivity misalnya setelah onCreate ()

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

}

Anda harus menemukan bahwa mengklik daftar nomor telepon Anda menyelesaikan aktivitas Anda, membuat panggilan ke nomor tersebut dan kembali ke aktivitas Anda ketika panggilan berakhir.

Melakukan panggilan dari luar aplikasi Anda saat itu masih ada tidak akan memulai kembali aktivitas Anda (kecuali jika itu sama dengan nomor BParty terakhir yang dipanggil).

:)


5
Maaf tapi kode ini terlihat agak jelek. Terima kasih atas jawabannya
Pierre

7

Anda dapat menggunakan startActivityForResult ()


1
Menggunakan Android 5.0 metode onActivityResult adalah panggilan langsung panggilan dimulai !!
Panciz

6

Ini solusi dari sudut pandang saya:

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

    }

Tentu saja dalam definisi Activity (class) Anda harus mengimplementasikan View.OnClickListener.


6

Ini adalah contoh saya, pertama pengguna dapat menulis nomor yang dia ingin panggil dan kemudian menekan tombol panggil dan diarahkan ke telepon. Setelah pembatalan panggilan, pengguna akan dikirim kembali ke aplikasi. Untuk itu, tombol ini perlu memiliki metode onClick ('makePhoneCall' dalam contoh ini) di xml. Anda juga perlu mendaftarkan izin dalam manifes.

Nyata

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

Aktivitas

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" />

Anda bahkan tidak mengerti apa yang Anda bicarakan. READ_PHONE_STATE - Anda tidak menggunakannya dalam kode contoh Anda, mengapa Anda menambahkannya? tentu saja itu akan mengembalikan Anda kembali ke aktivitas aplikasi Anda jika Anda menekan tombol pembatalan, tetapi penulis pertanyaan bertanya tentang bagaimana untuk kembali ke aktivitas setelah panggilan diterima
user924

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

Jika Anda akan menggunakan pendengar, Anda juga perlu menambahkan izin ini ke manifes.

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

3

Di dalam PhoneStateListener setelah melihat panggilan selesai digunakan dengan lebih baik:

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

Di mana CallDispatcherActivity adalah aktivitas di mana pengguna telah meluncurkan panggilan (ke operator layanan taksi, dalam kasus saya). Ini hanya menghilangkan aplikasi telepon Android dari atas, pengguna kembali bukan kode jelek yang saya lihat di sini.


1
Dan jangan lupa untuk menghapus pendengar setelah panggilan telepon selesai, seperti ini:((TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE)).listen(this, LISTEN_NONE);
Dmitri Novikov

Saya sudah mencoba menggunakan pendekatan Anda tetapi aktivitas (disebut ControlPanel) tidak diaktifkan kembali. Layar terus menunjukkan antarmuka dialer telepon dan logger pada titik masuk onResume dan onNewIntent dalam ControlPanel benar-benar diam. Berikut maksud: Intent intentRestart = new Intent(ControlPanel.this, ControlPanel.class);. Saya harus menunjukkan bahwa PhoneStateListener juga dalam ControlPanel. Yaitu, Tujuan saya adalah mengembalikan UI ke keadaan sebelum memulai panggilan telepon. Ada saran?
PeteH

Coba masuk ke dalam implementasi PhoneStateListener Anda.
Dmitri Novikov

3

Untuk kembali ke Anda Activity, Anda perlu mendengarkan TelephonyStates. Pada itu listenerAnda dapat mengirim Intentuntuk membuka kembali Activitysetelah ponsel dalam keadaan diam.

Setidaknya begitulah cara saya akan melakukannya.


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

Coba gunakan:

finish();

di akhir kegiatan. Ini akan mengarahkan Anda ke aktivitas Anda sebelumnya.


2

Saat PhoneStateListenerdigunakan, seseorang perlu memastikan bahwa PHONE_STATE_IDLEa PHONE_STATE_OFFHOOKdigunakan untuk memicu tindakan yang harus dilakukan setelah panggilan. Jika pemicu terjadi saat melihat PHONE_STATE_IDLE, Anda akan berakhir melakukannya sebelum panggilan. Karena Anda akan melihat statusnya berubahPHONE_STATE_IDLE -> PHONE_STATE_OFFHOOK -> PHONE_STATE_IDLE.


bukankah mungkin aplikasi berhenti ketika layar panggilan yang sedang terbuka terbuka?
lisovaccaro

Objek pendengar sekali diatur untuk mendengarkan TelephonyManager dengan ((TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE)).listen(new PhoneStateListener(), PhoneStateListener.LISTEN_CALL_STATE)akan terus mendengarkan keadaan telepon dan aktif sampai secara eksplisit dihentikan dengan((TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE)).listen(this, LISTEN_NONE)
PonMaran

2

// di setonclicklistener masukkan kode ini:

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

// berikan izin untuk panggilan dalam manifes:

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

1

@ Dmitri Novikov, FLAG_ACTIVITY_CLEAR_TOPmenghapus semua instance aktif di atas yang baru. Jadi, ini bisa mengakhiri instance lama sebelum menyelesaikan proses.



1

Langkah:

1) Tambahkan izin yang diperlukan dalam Manifest.xmlfile.

<!--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) Buat pendengar untuk perubahan status ponsel.

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) Inisialisasi pendengar di blog Anda OnCreate

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

tetapi jika Anda ingin melanjutkan aplikasi status terakhir Anda atau membawanya kembali dari tumpukan belakang , lalu ganti FLAG_ACTIVITY_CLEAR_TOPdenganFLAG_ACTIVITY_SINGLE_TOP

Referensi Jawaban ini



0

Saat memulai panggilan Anda, itu terlihat baik-baik saja.

Ada perbedaan antara Android 11+ dan ke bawah dalam membawa aplikasi Anda ke depan.

Android 10 atau kurang, Anda harus memulai niat baru, Android 11+ cukup Anda gunakan BringTaskToFront

Dalam IDLE status panggilan:

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

Saya mengatur MyActivity.MyActivityTaskIdketika melakukan panggilan pada aktivitas saya seperti itu, ini tidak berfungsi, atur variabel ini pada halaman aktivitas induk dari halaman yang Anda ingin kembali.

MyActivity.MyActivityTaskId = this.getTaskId();

MyActivityTaskId adalah variabel statis di kelas aktivitas saya

public static int MyActivityTaskId = 0;

Saya harap ini akan berhasil untuk Anda. Saya menggunakan kode di atas sedikit berbeda, saya membuka aplikasi saya segera setelah panggilan dijawab agar pengguna dapat melihat rincian penelepon.

Saya telah mengatur beberapa hal dalam AndroidManifest.xml:

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

dan izin:

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

Silakan ajukan pertanyaan jika atau ketika Anda buntu.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.