簡體   English   中英

在Android 6.0中接聽來電

[英]Answer Incoming Call in Android 6.0

有沒有辦法在沒有root權限的情況下以編程方式應答Android 6.0中的來電? 我嘗試了以下方法:

  1. 內部的ITelephony.aidl方法 -這樣我就可以結束通話。 但是接聽電話需要android.permission.MODIFY_PHONE_STATE ,Android 6.0中未提供給第三方應用程序。
  2. 耳機KeyCode意圖方法 這似乎根本不起作用。

希望這會有所幫助:)

public void acceptCall() {
        if (Build.VERSION.SDK_INT >= 21) {
            Intent answerCalintent = new Intent(context, AcceptCallActivity.class);
            answerCalintent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
            answerCalintent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(answerCalintent);
        } else {
            Intent intent = new Intent(context, AcceptCallActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);
        }
    }

AcceptCallActivity.java

import android.app.Activity;
import android.app.KeyguardManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.view.KeyEvent;
import android.view.WindowManager;

import java.io.IOException;
import java.util.logging.Logger;


public class AcceptCallActivity extends Activity {

    private static Logger logger = Logger.getLogger(String.valueOf(AcceptCallActivity.class));

    private static final String MANUFACTURER_HTC = "HTC";

    private KeyguardManager keyguardManager;
    private AudioManager audioManager;
    private CallStateReceiver callStateReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
        audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    }

    @Override
    protected void onResume() {
        super.onResume();

        registerCallStateReceiver();
        updateWindowFlags();
        acceptCall();
    }

    @Override
    protected void onPause() {
        super.onPause();

        if (callStateReceiver != null) {
            unregisterReceiver(callStateReceiver);
            callStateReceiver = null;
        }
    }

    private void registerCallStateReceiver() {
        callStateReceiver = new CallStateReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
        registerReceiver(callStateReceiver, intentFilter);
    }

    private void updateWindowFlags() {
        if (keyguardManager.inKeyguardRestrictedInputMode()) {
            getWindow().addFlags(
                    WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
                            WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
                            WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
        } else {
            getWindow().clearFlags(
                    WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
                            WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
                            WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
        }
    }

    private void acceptCall() {

        // for HTC devices we need to broadcast a connected headset
        boolean broadcastConnected = MANUFACTURER_HTC.equalsIgnoreCase(Build.MANUFACTURER)
                && !audioManager.isWiredHeadsetOn();

        if (broadcastConnected) {
            broadcastHeadsetConnected(false);
        }

        try {

            try {
               // logger.debug("execute input keycode headset hook");
                Runtime.getRuntime().exec("input keyevent " +
                        Integer.toString(KeyEvent.KEYCODE_HEADSETHOOK));

            } catch (IOException e) {
                // Runtime.exec(String) had an I/O problem, try to fall back
            //    logger.debug("send keycode headset hook intents");
                String enforcedPerm = "android.permission.CALL_PRIVILEGED";
                Intent btnDown = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(
                        Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN,
                                KeyEvent.KEYCODE_HEADSETHOOK));
                Intent btnUp = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(
                        Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP,
                                KeyEvent.KEYCODE_HEADSETHOOK));

                sendOrderedBroadcast(btnDown, enforcedPerm);
                sendOrderedBroadcast(btnUp, enforcedPerm);
            }
        } finally {
            if (broadcastConnected) {
                broadcastHeadsetConnected(false);
            }
        }
    }

    private void broadcastHeadsetConnected(boolean connected) {
        Intent i = new Intent(Intent.ACTION_HEADSET_PLUG);
        i.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
        i.putExtra("state", connected ? 1 : 0);
        i.putExtra("name", "mysms");
        try {
            sendOrderedBroadcast(i, null);
        } catch (Exception e) {
        }
    }

    private class CallStateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            finish();
        }
    }
}

測試了最新版本的棉花糖。

干杯!

經過大量研究后,我發布了在Orasi中使用的代碼。 希望這對許多程序員有幫助...請注意,此代碼是從具有其他功能的軟件中提取的,因此某些代碼可能不會在所有軟件中使用。

首先,在所有Android版本上都可以應答並結束呼叫的功能(無AIDL!):

/////////////////////////////////////////////////////////////////////////////////////
// Controle le téléphone en utilisant des primitives selon les versions d'OS
private void PhoneControl(int nControl) {
    if(nControl == PHONE_END_CALL) { // End call, all Android version
        try {
            TelephonyManager tm = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
            if(tm == null)
                return;
            tm.getClass().getMethod("endCall").invoke(tm);
            bIsEnding = true;
        } catch (Exception e) { /* Do Nothing */ }
    }

    if(nControl == PHONE_ACCEPT_CALL) { // Accept phone call
        if(!bCallAccepted) { // Call déjà accepté => pas d'action (évite double action)
            bCallAccepted = true;
            if(Build.VERSION.SDK_INT >= 26) { // Pris en charge Android >= 8.0
                if(checkSelfPermission("android.permission.ANSWER_PHONE_CALLS") == PackageManager.PERMISSION_GRANTED) {
                    TelecomManager tm = (TelecomManager) this.getSystemService(Context.TELECOM_SERVICE);
                    if(tm != null)
                        tm.acceptRingingCall();
                }
            }
            if(Build.VERSION.SDK_INT >= 23 && Build.VERSION.SDK_INT < 26) { // Hangup in Android 6.x and 7.x
                MediaSessionManager mediaSessionManager =  (MediaSessionManager) getApplicationContext().getSystemService(Context.MEDIA_SESSION_SERVICE);
                if(mediaSessionManager != null) {
                    try {
                        List<android.media.session.MediaController> mediaControllerList = mediaSessionManager.getActiveSessions
                                (new ComponentName(getApplicationContext(), NotificationReceiverService.class));

                        for (android.media.session.MediaController m : mediaControllerList) {
                            if ("com.android.server.telecom".equals(m.getPackageName())) {
                                m.dispatchMediaButtonEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK));
                                m.dispatchMediaButtonEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));
                                break;
                            }
                        }
                    } catch (Exception e) { /* Do Nothing */ }
                }
            }
            if(Build.VERSION.SDK_INT < 23) { // Prend en charge jusqu'à Android 5.1
                try {
                    if(Build.MANUFACTURER.equalsIgnoreCase("HTC")) { // Uniquement pour HTC
                        AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
                        if(audioManager!=null && !audioManager.isWiredHeadsetOn()) {
                            Intent i = new Intent(Intent.ACTION_HEADSET_PLUG);
                            i.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                            i.putExtra("state", 0);
                            i.putExtra("name", "Orasi");
                            try {
                                sendOrderedBroadcast(i, null);
                            } catch (Exception e) { /* Do Nothing */ }
                        }
                    }
                    Runtime.getRuntime().exec("input keyevent " +
                            Integer.toString(KeyEvent.KEYCODE_HEADSETHOOK));
                } catch (Exception e) {
                    // Runtime.exec(String) had an I/O problem, try to fall back
                    String enforcedPerm = "android.permission.CALL_PRIVILEGED";
                    Intent btnDown = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(
                            Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN,
                                    KeyEvent.KEYCODE_HEADSETHOOK));
                    Intent btnUp = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(
                            Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP,
                                    KeyEvent.KEYCODE_HEADSETHOOK));

                    this.sendOrderedBroadcast(btnDown, enforcedPerm);
                    this.sendOrderedBroadcast(btnUp, enforcedPerm);
                }
            }
        }
    }
}

二,權限:

    if(Build.VERSION.SDK_INT >= 26) { // Permission necessaire
        if(checkSelfPermission("android.permission.ANSWER_PHONE_CALLS") != PackageManager.PERMISSION_GRANTED) {
            String szPermissions[] = {"android.permission.ANSWER_PHONE_CALLS"};
            requestPermissions(szPermissions, 0);
        }
    }

    if(Build.VERSION.SDK_INT >= 23 && bUseScreen ) { // Permission necessaire
        if(checkSelfPermission("android.permission.SYSTEM_ALERT_WINDOW") != PackageManager.PERMISSION_GRANTED) {
            Intent myIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
            startActivity(myIntent);
        }
        if(Build.VERSION.SDK_INT < 26) { // Permission pour Android 6.x et 7.x
            ContentResolver contentResolver = getContentResolver();
            String enabledNotificationListeners = Settings.Secure.getString(contentResolver, "enabled_notification_listeners");
            String packageName = getPackageName();
            if (enabledNotificationListeners == null || !enabledNotificationListeners.contains(packageName)) {
                Intent intent2 = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS);
                startActivity(intent2);
            }
        }
    }

請注意,有一個“覆蓋”權限,而不是直接接聽電話。

通知接收者服務:

package mss.micromega.pmignard.orasi;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.os.Build;
import android.service.notification.NotificationListenerService;

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
@SuppressLint("OverrideAbstract")
public class NotificationReceiverService extends NotificationListenerService {
    public NotificationReceiverService() {
    }
}

表現:

    <service android:name=".NotificationReceiverService"
             android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
             android:enabled="true"
             android:exported="true" >
            <intent-filter>
                <action android:name="android.service.notification.NotificationListenerService" />
            </intent-filter>
    </service>

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

問候。

編輯,我沒有使用好的帳戶

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM