アンドロイドで電話をかけ、電話が終わったら私の活動に戻る方法は?


129

電話をかけるアクティビティを起動していますが、[通話終了]ボタンを押してもアクティビティに戻りません。「通話終了」ボタンが押されたときに戻ってくる通話アクティビティをどのように起動できますか?これは私が電話をかける方法です:

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

回答:


106

PhoneStateListenerを使用して、通話がいつ終了したかを確認します。ほとんどの場合、呼び出しが開始するのを待ち(PHONE_STATE_OFFHOOKからPHONE_STATE_IDLEに再度変更されるまで待機する)リスナーアクションをトリガーしてから、アプリをIDLE状態に戻すためのコードを記述する必要があります。

サービスでリスナーを実行して、アプリが再起動されるようにする必要がある場合があります。いくつかのサンプルコード:

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

リスナー定義:

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

あなたにはManifest.xml、ファイル、次の権限を追加します

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

10
許可をお忘れなく。;)
Gp2mv3 2012年

5
Gp2mv3が指摘したように、AndroidManifest.xmlにREAD_PHONE_STATE権限を追加することを忘れないでください。
クーパー

6
@moonlightcheese通話アプリからアプリに戻るためのコードを追加できますか?
オタク2013

電話をかけるたびに常にアプリのアクティビティが開かれるため、これは危険です
user924

49

これはスターターからの質問に関するものです。

コードの問題は、数値を適切に渡していないことです。

コードは次のようになります。

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

マニフェストファイルに権限を追加することを忘れないでください。

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

または

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

万が一の場合に備えて緊急番号用DIAL


7
あなたのコードが元の質問のコードとどのように異なるかを確認するのに苦労しています
Elijah Saounkine

コードは同じです。マニフェストファイルに権限を追加する必要があります。
Pria

4
android.permission.CALL_PRIVILEGED権限は、アプリレベルでは使用できないシステムアプリにのみ付与されます。
CoDe 2014年

そしてそれは何ですか?それはあなたの活動に戻りません
user924

24

同じ問題がありPhoneStateListener、呼び出しをいつ終了するかを特定するためにa を使用してそれを解決することができましたが、さらに、finish()で再開する前に元のアクティビティをstartActivity使用する必要がありました。


4
別の方法を使用してこれを回避できます。Androidの通話ログを監視するContentObserverを作成した場合、通話ログが変更されるまでアプリは起動しません。私のアプリは通話ログデータを必要とし、変更が行われる前にリスナーが戻っていたため、実際にはこのモデルを優先してPhoneStateListenerをダンプする必要がありました。 pastebin.com/bq2s9EVa
moonlightcheese

11
@André:リンクが壊れているようです
aggregate116​​6877

私はあなたに百万の評判を与えます(私がたくさんあった場合:))私の一日をありがとう!
keybee 2013

1
私が言うリンクの問題!
Dheeraj Bhaskar

救助へのインターネットアーカイブ... web.archive.org/web/20120123224619/http://umamao.com/questions/...
基本

13

EndCallListenerが最も機能的な例であり、説明されている動作(finish()、call、restart)を取得するために、いくつかのSharedPreferencesを追加して、Listenerがこの動作を管理するための参照を持つようにしました。

OnClick、initialize、EndCallListenerは、アプリからの呼び出しにのみ応答します。他の呼び出しは無視されました。

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

        }

    }
}

これらを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>

呼び出しの前にルックアンドフィールに戻る必要がある場合、マニフェストでこのようなもの

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

これらを「myActivity」に入れます

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

これを使用して、myActivityのonClickの動作を初期化します(例: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();

}

電話番号のリストをクリックすると、アクティビティが終了し、番号に電話をかけ、通話が終了するとアクティビティに戻ります。

アプリの実行中にアプリの外部から電話をかけても、アクティビティは再開されません(最後に呼び出されたBParty番号と同じでない限り)。

:)


5
申し訳ありませんが、このコードはやや醜く見えます。答えをありがとう
ピエール

7

あなたはstartActivityForResult()を使うことができます


1
Android 5.0を使用すると、onActivityResultメソッドがすぐに呼び出され、呼び出しが開始されます!!
Panciz 2017年

6

これは私の観点からの解決策です:

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

    }

もちろん、アクティビティ(クラス)定義では、View.OnClickListenerを実装する必要があります。


6

これが私の例です。最初に、ユーザーは自分がダイヤルしたい番号を入力してから、通話ボタンを押して電話に転送されます。通話のキャンセル後、ユーザーはアプリケーションに送り返されます。これを行うには、ボタンのxmlにonClickメソッド(この例では「makePhoneCall」)が必要です。また、マニフェストに権限を登録する必要があります。

マニフェスト

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

アクティビティ

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

あなたはあなたが話していることすら知りません。READ_PHONE_STATE-コード例では使用していませんが、なぜ追加したのですか?もちろん、キャンセルボタンを押すと、アプリのアクティビティに戻りますが、質問の作成者は、通話が受け入れられた後にアクティビティに戻る方法について尋ねました
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

リスナーを使用する場合は、この権限をマニフェストにも追加する必要があります。

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

3

呼び出しが適切に終了した後のPhoneStateListenerの内部:

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

ここで、CallDispatcherActivityは、ユーザーが(私の場合、タクシーサービスディスパッチャーへの)呼び出しを開始したアクティビティです。これはAndroidテレフォニーアプリを上から削除するだけで、ユーザーはここで見た醜いコードの代わりに戻ってきます。


1
:と電話がこのように、実行された後、リスナーを削除することを忘れないでください((TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE)).listen(this, LISTEN_NONE);
ドミトリ・ノビコフ

私はあなたのアプローチを試してみましたが、アクティビティ(ControlPanelと呼ばれます)が再アクティブ化されていません。ディスプレイには引き続き電話ダイヤラインターフェイスが表示され、ControlPanel内のonResumeおよびonNewIntentエントリポイントのロガーは完全に無音です。ここに意図があります:Intent intentRestart = new Intent(ControlPanel.this, ControlPanel.class);。PhoneStateListenerもControlPanel内にあることを指摘しておきます。つまり、私の目標は、UIを通話を開始する前の状態に戻すことです。助言がありますか?
PeteH 2013

PhoneStateListener実装内でログを記録してみてください。
ドミトリ

3

に戻るには、Activityを聞く必要がありますTelephonyStates。その上で、電話がアイドル状態になったlistenerときにを送信してIntent、再び開くことができますActivity

少なくともそれが私がやる方法です。


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

使ってみてください:

finish();

活動の終わりに。以前のアクティビティにリダイレクトされます。


2

PhoneStateListenerを使用する場合、コール後に実行されるアクションをトリガーするためにPHONE_STATE_IDLE次のa PHONE_STATE_OFFHOOKを使用することを確認する必要があります。を見てトリガーが発生するPHONE_STATE_IDLEと、呼び出しの前にトリガーが発生します。状態変化が見えるのでPHONE_STATE_IDLE -> PHONE_STATE_OFFHOOK -> PHONE_STATE_IDLE.


進行中の通話画面が開いたときにアプリが停止することはありませんか?
lisovaccaro 2013年

TelephonyManagerをリッスンするように設定されたリスナーオブジェクトは ((TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE)).listen(new PhoneStateListener(), PhoneStateListener.LISTEN_CALL_STATE)、電話状態をリッスンし続け、明示的に停止されるまでアクティブになります((TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE)).listen(this, LISTEN_NONE)
PonMaran

2

// setonclicklistenerに次のコードを追加します:

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

//マニフェストでの呼び出しを許可します:

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

1

@Dmitri Novikov FLAG_ACTIVITY_CLEAR_TOPは、新しいインスタンスの上にあるアクティブなインスタンスをすべてクリアします。そのため、プロセスが完了する前に古いインスタンスが終了する可能性があります。



1

手順:

1)必要な権限をManifest.xmlファイルに追加します。

<!--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)電話の状態変更のリスナーを作成します。

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)でリスナーを初期化します OnCreate

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

しかし、あなたのアプリケーション最後の状態を再開するか、バック、バックスタックからそれを持参する場合は、交換してくださいFLAG_ACTIVITY_CLEAR_TOPFLAG_ACTIVITY_SINGLE_TOP

この回答を参照



0

通話を開始すると、問題ありません。

ただし、アプリを前面に表示する方法には、Android 11以降との違いがあります。

新しいインテントを開始するために必要なAndroid 10以下、単に使用するAndroid 11以降 BringTaskToFront

呼び出し状態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.MyActivityTaskIdのように自分のアクティビティを呼び出すときにを設定しましたが、これは機能しません。戻りたいページの親アクティビティページにこの変数を設定します。

MyActivity.MyActivityTaskId = this.getTaskId();

MyActivityTaskId 私の活動クラスの静的変数です

public static int MyActivityTaskId = 0;

これがうまくいくことを願っています。上記のコードの使用方法が少し異なります。通話に応答するとすぐにアプリを開いて、ユーザーが発信者の詳細を確認できるようにします。

私もいくつかのものを設定しAndroidManifest.xmlました:

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

と権限:

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

行き詰まった場合、または行き詰まった場合は質問してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.