start and end call use itelephony

网上扒的通过添加一个ITelephony.aidl来反射可是并没有成功。提示无法引入这个文件。

这里解释了一下原理;

使用java 反射来获取安卓内部的私有方法

TelephonyManager 类是由远程服务来实现的,它实质是

package org.nd.ui;

import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
import android.widget.Toast;

import org.nd.R;

import java.lang.reflect.Method;

import org.nd.common.Common;

/**
 * Created by HAO on 2015/7/17.
 */
public class FragmentCallPhone extends Fragment implements View.OnClickListener {

    public FragmentCallPhone() {
    }

    private Button btnCall, btnEnd;
    private TextView edit_phone;
    private static final int AUTO_END_CALL_AFTER_ONE_MINUTE = 10000;
    private Handler mHandler;
    private Handler cutHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case Common.HEART_BEAT:
                    Log.d("org.nd", "HEART_BEAT_TWO");
                    break;
                case Common.REFLECTION_ERROR:
                    Log.d("org.nd", "HEART_BEAT_THREE");
                    break;
                case Common.HEART_BEAT_TWO:
                    Log.d("org.nd", "HEART_BEAT_ONE ");
                    break;
            }
        }
    };
    private boolean call_once = true;

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_layout_call, container, false);
        btnCall = (Button) view.findViewById(R.id.call_phone);
        btnCall.setOnClickListener(this);
        btnEnd = (Button) view.findViewById(R.id.dial_and_call);
        btnEnd.setOnClickListener(this);
        edit_phone = (TextView) view.findViewById(R.id.edit_phone);

        MyPhoneListener phoneListener = new MyPhoneListener();
        TelephonyManager telephonyManager =

                (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE);
        telephonyManager.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);
        mHandler = new Handler();
        return view;
    }

    @Override
    public void onResume() {
        super.onResume();
       // btnCall.callOnClick();
    }

    @Override
    public void onClick(View v) {
        String uri, number = edit_phone.getText().toString();
        switch (v.getId()) {
            case R.id.call_phone:
                if (number.isEmpty())
                    number = "10000";
                //   if(!autoEnd.isChecked())
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        call_once = false;
                        TelephonyManager telephonyManager = (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE);

                        Message msg = new Message();
                        try {
                            Class c = Class.forName(telephonyManager.getClass().getName());
                            Method m = c.getDeclaredMethod("getITelephony");
                            m.setAccessible(true);
                            Object telephonyService = m.invoke(telephonyManager); // Get the internal ITelephony object
                            c = Class.forName(telephonyService.getClass().getName()); // Get its class
                            m = c.getDeclaredMethod("endCall"); // Get the "endCall()" method
                            m.setAccessible(true); // Make it accessible
                            m.invoke(telephonyService); // invoke endCall()
                            msg.what = Common.HEART_BEAT;
                            cutHandler.sendMessage(msg);
                        } catch (Exception e) {
                            msg = new Message();
                            msg.what = Common.REFLECTION_ERROR;
                            cutHandler.sendMessage(msg);
                            Log.d("org.nd", e.toString());
                        }
                    }
                }, AUTO_END_CALL_AFTER_ONE_MINUTE);

                uri = "tel:" + number;
                Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse(uri));
                startActivity(callIntent);
                Message msg = new Message();
                msg.what = Common.HEART_BEAT_TWO;
                cutHandler.sendMessage(msg);
                break;
            case R.id.dial_and_call:
                uri = "tel:" + edit_phone.getText().toString();
                Intent dialIntent = new Intent(Intent.ACTION_DIAL, Uri.parse(uri));
                startActivity(dialIntent);
                break;

        }
    }

    private class MyPhoneListener extends PhoneStateListener {
        private boolean onCall = false;

        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            switch (state) {
                case TelephonyManager.CALL_STATE_RINGING:
                    // phone ringing...
                    Toast.makeText(getActivity(), incomingNumber + " calls you",
                            Toast.LENGTH_LONG).show();
                    break;
                case TelephonyManager.CALL_STATE_OFFHOOK:
                    // one call exists that is dialing, active, or on hold
                    Toast.makeText(getActivity(), "on call...",
                            Toast.LENGTH_LONG).show();
                    //because user answers the incoming call
                    onCall = true;
                    break;
                case TelephonyManager.CALL_STATE_IDLE:
                    // in initialization of the class and at the end of phone call
                    // detect flag from CALL_STATE_OFFHOOK
                    if (onCall == true) {
                        Toast.makeText(getActivity(), "restart app after call",
                                Toast.LENGTH_LONG).show();
                        // restart our application
                        Intent restart = getActivity().getBaseContext().getPackageManager().
                                getLaunchIntentForPackage(getActivity().getBaseContext().getPackageName());
                        restart.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                        startActivity(restart);
                        onCall = false;
                    }
                    break;
                default:
                    break;
            }
        }
    }
}

调用远程电话服务,这个工作具体是由AIDL来做的,remote procedure call  (RPC)

这样远程服务使用公有TelephonyManager 就可以不暴露实现,你需要做的就是利用 getITelephony() 来得到远程程序调用的客户端,此方法返回一个ITelephony类型的对象。

有了这个对象,就可以得到其类对象和内部方法endCall() ,这样我们就能调用这个方法。

现在这个endCall() 是运行在远程程序调用的客户端,它可以发送消息给 远程电话服务(运行在远程服务中),要求终止当前通话。

由于源代码 ITelephony.aidl 是公开的,你可以将代码放在你的工程中,IDE会自动生成ITelephony.java(自动包含了RPC的客户端)

当你在安卓设备上运行时,会调用安卓框架里的ITelephony 对象,并将其转换成 com.android.internal.telephony.ITelephony

————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

附上我的实现:

AndroidManifest.xml

...
    <uses-permission android:name="android.permission.CALL_PHONE"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="ANDROID.PERMISSION.MODIFY_PHONE_STATE"/>
...
FragmentCallPhone.java
时间: 2024-10-17 02:47:13

start and end call use itelephony的相关文章

Android5.0以上系统的移动网络开关

笔者近期遇到一个非常有意思的bug,贴出来和大家分享下. 那是一个温暖的早晨,阳光晒得人非常舒服.一封bug邮件像一片叶子飘到我的邮箱. 一番交流.笔者确认负责的Widget开关在Android5.0以上系统没有作用.相信非常多做过移动网络开关的朋友都知道.传统的方法是在ConnectivityManager中通过反射两个方法setMobileDataEnabled和getMobileDataEnabled来控制移动网络开和关的. /** * Gets the value of the sett

android 电话监听和拦截

一.首先在manifest.xml文件中获取监听电话权限,注册监听电话的Activity <receiver android:name=".PhoneReceiver"> <intent-filter android:priority="1000"> <action android:name="android.intent.action.PHONE_STATE"/> <action android:nam

Android-使用AIDL挂断电话

1.AIDL简单操作 package org.zrf.demo; import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method; import android.app.Service;import android.content.Context;import android.content.Intent;import android.media.AudioManager;import andr

手机卫士06_挂电话拦截短信,资产目录_来电去电_自定义吐司

1.1 反射调用系统隐藏api挂掉电话 Android 1.5之前可以通过 TelephonyManager,tm.endCall();//但是列表找不到 谷歌认为挂掉电话是危及手机根本功能的动作,所以隐藏了这个api 在1.5之后,要通过反射调用这一api才能实现 两个网站 ①www.greocide.com //搜索源码的网站 搜索TelephonyManager,查找版本最低的版本即可(越低越容易理解) 这个api被隐藏掉了,不能直接获取到TelephonyManager.对象. ②通过g

android143 360 短信电话拦截

package com.itheima.mobileguard.services; import java.lang.reflect.Method; import android.app.Service; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; im

Android之——自动挂断电话的实现

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47072451 通过<Android之--AIDL小结>与<Android之--AIDL深入>两篇博文,相信大家已经对Android AIDL有了一定的了解,下面,我们就利用Android的AIDL实现自动挂断电话的功能,好了,不多说了,我们直接进入主题. 1.准备AIDL文件 挂断电话的AIDL文件都是Android自带的文件,我们可以从Android的源代码中找到

黑马程序员--------来电拦截

第一步:在程序中新建一个包,包名必须为:com.android.internal.telephony,因为要使用aidl. 第二步:在这个包里面新建一个名为ITelephony.aidl的文件,然后在文件里面写入代码: <span style="font-size:14px;"> package com.android.internal.telephony; <span style="white-space:pre"> </span&g

Android4.0(Phone)拨号启动过程分析(二)

接上:Android4.0(Phone)拨号启动过程分析(一) InCallScreen处理来电和拨号的界面,接通电话也是这个界面,接下来分析InCallScreen类是如何处理拨号流程的: @Override protected void onCreate(Bundle icicle) { Log.i(LOG_TAG, "onCreate()... this = " + this); Profiler.callScreenOnCreate(); super.onCreate(icic

Class.forName()的作用与使用总结

1.Class类简介: Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识.这项信息纪录了每个对象所属的类.虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类.Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建. Class 没有公共构造方法.Class 对象是在加载类时由Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象. 虚拟