android 監聽電話去電接通瞬間[非來電]

來源:互聯網
上載者:User

首先感歎一下android強大,它可以把同一個apk裡面得不同Actvity分別運行在不同的進程中,比如我想讓自己的應用中Activity運行在Phone進程中,那麼我需要做三個事情。

本文包含三個知識點:

1.監聽去電接通     2.apk擷取root許可權 3. 運行時將apk push 到system/app

(1)

 

[java]
<activity   
ndroid:process="com.android.phone" 
            android:label="@string/app_name"   
            android:name=".AutoCallActivity" >   
               
        </activity>   

    <activity 
   android:process="com.android.phone"
                android:label="@string/app_name" 
                android:name=".AutoCallActivity" > 
                 
            </activity>  (2)


[java]
<manifest xmlns:android="http://schemas.android.com/apk/res/android"   
    package="com.spreadst.drag"   
    coreApp="true"   
oid:sharedUserId="android.uid.system" 
    android:versionCode="1"   

    <manifest xmlns:android="http://schemas.android.com/apk/res/android" 
        package="com.spreadst.drag" 
        coreApp="true" 
android:sharedUserId="android.uid.system"
        android:versionCode="1" 
(3) [java]
   LOCAL_PACKAGE_NAME := autocall   
    #LOCAL_CERTIFICATE := shared   
LOCAL_CERTIFICATE := platform  

    LOCAL_PACKAGE_NAME := autocall 
    #LOCAL_CERTIFICATE := shared 
LOCAL_CERTIFICATE := platform 為什麼會有這個需求呢?TelephonyManager 中狀態 只有  IDLE 空閑狀態, 來電接通狀態 ,撥打狀態,沒有去電接通狀態,參考phone中得實現如下:
Phone  phone = PhoneFactory.getDefaultPhone();
這個調用是不能運行在phone以外的進程中的,不信你可以試一下,請記住一個進程的主線程的looper是唯一的

原因如下:

[java]
if (sLooper != Looper.myLooper()) { 
            throw new RuntimeException( 
                "PhoneFactory.getDefaultPhone must be called from Looper thread"); 
        } 

if (sLooper != Looper.myLooper()) {
            throw new RuntimeException(
                "PhoneFactory.getDefaultPhone must be called from Looper thread");
        }去電接通若干秒之後掛斷代碼如下,由於使用了hide class,所以必須在android原始碼底下編譯,當然你也可以通過反射、AIDL、class.jar等方式解決這個問題。


[java]
CallManager mCM = CallManager.getInstance();   
   Phone  phone = PhoneFactory.getDefaultPhone();   
   
mCM.registerPhone(phone);   
       mCM.registerForPreciseCallStateChanged(mHandler, PHONE_STATE_CHANGED, null);  

CallManager mCM = CallManager.getInstance(); 
   Phone  phone = PhoneFactory.getDefaultPhone(); 
 
mCM.registerPhone(phone); 
       mCM.registerForPreciseCallStateChanged(mHandler, PHONE_STATE_CHANGED, null);
[java]
private Handler mHandler=new Handler(){   
   
        public void handleMessage(android.os.Message msg) {   
            switch (msg.what) {   
            case PHONE_STATE_CHANGED:   
                updatePhoneSateChange();   
                break;   
            default:   
                break;   
            }   
        };   
           
    };   

    private Handler mHandler=new Handler(){ 
     
            public void handleMessage(android.os.Message msg) { 
                switch (msg.what) { 
                case PHONE_STATE_CHANGED: 
                    updatePhoneSateChange(); 
                    break; 
                default: 
                    break; 
                } 
            }; 
             
        }; 
[java]
private void updatePhoneSateChange(){   
        Call fgCall = mCM.getActiveFgCall();   
        if (mCM.hasActiveRingingCall()) {   
                fgCall = mCM.getFirstActiveRingingCall();   
          }   
   
        final Call.State state = fgCall.getState();   
        switch (state) {   
            case IDLE:   
                break;   
   
            case ACTIVE://去電接通    
                Log.d("yzy","ACTVIE");   
                final Timer timer = new Timer();   
                if(mode == Mode.mode2){   
                    timer.schedule(new TimerTask() {   
                        @Override   
                        public void run() {   
                            try {   
                                Log.d("yzy", "endcall()");   
   
                                mITelephony.endCall();   
                                timer.cancel();   
                            } catch (RemoteException e) {   
                                e.printStackTrace();   
                            }   
                        }   
                    }, holdonDuration * 1000, holdonDuration * 1000);   
                }   
                //mITelephony.endCall();    
                break;   
            default:   
                break;   
        }   
           
    }   

    private void updatePhoneSateChange(){ 
            Call fgCall = mCM.getActiveFgCall(); 
            if (mCM.hasActiveRingingCall()) { 
                    fgCall = mCM.getFirstActiveRingingCall(); 
              } 
     
            final Call.State state = fgCall.getState(); 
            switch (state) { 
                case IDLE: 
                    break; 
     
                case ACTIVE://去電接通 
                    Log.d("yzy","ACTVIE"); 
                    final Timer timer = new Timer(); 
                    if(mode == Mode.mode2){ 
                        timer.schedule(new TimerTask() { 
                            @Override 
                            public void run() { 
                                try { 
                                    Log.d("yzy", "endcall()"); 
     
                                    mITelephony.endCall(); 
                                    timer.cancel(); 
                                } catch (RemoteException e) { 
                                    e.printStackTrace(); 
                                } 
                            } 
                        }, holdonDuration * 1000, holdonDuration * 1000); 
                    } 
                    //mITelephony.endCall(); 
                    break; 
                default: 
                    break; 
            } 
             
        } 
如果你將這個apk 簡單的install 會報告如下錯誤:不存在該共用使用者或簽名不匹配,這是因為[java] view plaincopyprint?android:sharedUserId="android.uid.system" 

android:sharedUserId="android.uid.system"必須放到system/app目錄下才能工作。這就由牽扯出了兩個問題,臨時擷取root許可權與運行時拷貝.

其他關鍵代碼:


[java]
private ITelephony mITelephony; 
mITelephony = ITelephony.Stub.asInterface(ServiceManager 
                .getService(Context.TELEPHONY_SERVICE)); 
        mPhoneStateListener = getPhoneStateListener(); 
        ((TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE)).listen( 
                mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); 
private PhoneStateListener getPhoneStateListener() { 
 
        return new PhoneStateListener() { 
            @Override 
            public void onCallStateChanged(int state, String incomingNumber) { 
                try { 
                     Log.d("yzy"," state: " 
                     + mITelephony.getCallState()); 
 
                } catch (RemoteException e) { 
                    e.printStackTrace(); 
                } 
 
            } 
        }; 
 
    } 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.