Android中的自定义传入/传出呼叫屏幕

时间:2014-03-14 10:01:16

标签: android android-manifest

我正在尝试实现自定义传入/传出呼叫屏幕。以下是我的尝试。你提出了两个问题

  1. 有时它会调用手机上的默认传入屏幕,或者有时会调用自定义屏幕。我的电话总是打电话给定制的屏幕。

  2. 我无法发出传出电话。自定义屏幕刚出现但没有拨打任何电话。

  3. 如何解决这个问题,我不确定这里有什么问题。如果有人可以帮我解决这个问题会很棒。

    以下是我的尝试:

    清单:

    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
    <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
    
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.NoTitleBar" >
        <activity
            android:name="com.honey.ringer.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
    
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.honey.ringer.AcceptCall"
            android:screenOrientation="portrait"
            android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" >
            <intent-filter>
                <action android:name="android.intent.action.ANSWER" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    
        <receiver
            android:name="com.honey.ringer.PhoneListenerBroad">
            <intent-filter>
                <action android:name="android.intent.action.PHONE_STATE" />
                <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
            </intent-filter>
        </receiver>
    </application>
    

    BroadCastReciever:这有传入和传出

    public class PhoneListenerBroad extends BroadcastReceiver
    {
    
    Context c;
    private String outgoing;
    
    @Override
    public void onReceive(Context context, Intent intent) 
    {
        c = context;
    
        if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) 
        {
            outgoing = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER); 
            int state = 2;
            Intent intentPhoneCall = new Intent(c, AcceptCall.class);
            intentPhoneCall.putExtra("incomingnumber", outgoing);
            intentPhoneCall.putExtra("state", state);
            intentPhoneCall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            c.startActivity(intentPhoneCall);
        }
    
        try
        {
            TelephonyManager tmgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            MyPhoneStateListener PhoneListener = new MyPhoneStateListener();
            tmgr.listen(PhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
        }
        catch (Exception e) 
        {
            Log.e("Phone Receive Error", " " + e);
        }
    
    }
    
    private class MyPhoneStateListener extends PhoneStateListener
    {
        public void onCallStateChanged(final int state, final String incomingNumber) 
        {
            Handler callActionHandler = new Handler();
            Runnable runRingingActivity = new Runnable() 
            {
                @Override
                public void run() 
                {
                    if (state == 1)
                    {
                        Intent intentPhoneCall = new Intent(c, AcceptCall.class);
                        intentPhoneCall.putExtra("incomingnumber", incomingNumber);
                        intentPhoneCall.putExtra("state", state);
                        intentPhoneCall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        c.startActivity(intentPhoneCall);
                    }
                }
            };
    
            if (state == 1)
            {   
                callActionHandler.postDelayed(runRingingActivity, 100);
            }
    
            if (state == 0) 
            {
                callActionHandler.removeCallbacks(runRingingActivity);
            }
        }
    }
    

    }

    AcceptCall.java(用于UI目的 - 传入和传出):

     @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
     public class AcceptCall extends Activity implements OnClickListener 
     {
    LinearLayout answerButton;
    LinearLayout rejectButton;
    LinearLayout timerLayout;
    
    TextView contactName;
    TextView contactNumber;
    ImageView profile;
    
    private String incomingnumber;
    private int state;
    
    String name = null;
    String contactId = null;
    
    InputStream photo_stream;
    
    TextView callType;
    
    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.testactivity);
    
        answerButton = (LinearLayout) findViewById(R.id.callReceive);
        answerButton.setOnClickListener(this);
    
        rejectButton = (LinearLayout) findViewById(R.id.callReject);
        rejectButton.setOnClickListener(this);
    
        timerLayout = (LinearLayout) findViewById(R.id.timerLayout);
    
        contactName = (TextView) findViewById(R.id.contactName);
        contactNumber = (TextView) findViewById(R.id.contactNumber);
    
        callType = (TextView) findViewById(R.id.callType);
    
        timerValue = (TextView) findViewById(R.id.timerValue);
    
        profile  = (ImageView)findViewById(R.id.contactPhoto);     
    
        Bundle bundle =  getIntent().getExtras();
        if(bundle != null)
        {
            incomingnumber = bundle.getString("incomingnumber");
            state = bundle.getInt("state");
        }
    
        contactslookup(incomingnumber);
    
        contactName.setText(name);
        contactNumber.setText(incomingnumber);
    
    
        if (state == 2)
        {
            /*String uri = "tel:" + incomingnumber.trim();
            Intent intent = new Intent(Intent.ACTION_CALL);
            intent.setData(Uri.parse(uri));
            startActivity(intent);*/
        }
    
        PhoneStateListener phoneStateListener = new PhoneStateListener() 
        {
            @Override
            public void onCallStateChanged(int state, String incomingNumber) 
            {
                //wen ringing
                if (state == TelephonyManager.CALL_STATE_RINGING)
                {
                    Log.e("CALL_STATE_RINGING","CALL_STATE_RINGING");
                } 
    
                //after call cut
                else if(state == TelephonyManager.CALL_STATE_IDLE)
                {
                    RejectCall();
                } 
    
                //wen speaking / outgoing call
                else if(state == TelephonyManager.CALL_STATE_OFFHOOK)
                {
                    Log.e("CALL_STATE_OFFHOOK","CALL_STATE_OFFHOOK");
                }
                super.onCallStateChanged(state, incomingNumber);
            }
        };
        TelephonyManager mgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
        if(mgr != null) 
        {
            mgr.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
        }
    }
    
    
    private void contactslookup(String number) 
    {
    
        Log.v("ffnet", "Started uploadcontactphoto...");
    
        //InputStream input = null;
    
        // define the columns I want the query to return
        String[] projection = new String[] {ContactsContract.PhoneLookup.DISPLAY_NAME,ContactsContract.PhoneLookup._ID};
    
        // encode the phone number and build the filter URI
        Uri contactUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
    
        // query time
        Cursor cursor = getContentResolver().query(contactUri, projection, null, null, null);
    
        if (cursor.moveToFirst()) 
        {
            // Get values from contacts database:
            contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.PhoneLookup._ID));
            name =      cursor.getString(cursor.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME));
        } 
    
        else 
        {
            return; // contact not found
        }
    
    
        int currentapiVersion = android.os.Build.VERSION.SDK_INT;
        if (currentapiVersion >= 14)
        {
            Uri my_contact_Uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.parseLong(contactId));
            photo_stream = ContactsContract.Contacts.openContactPhotoInputStream(getContentResolver(), my_contact_Uri, true);
        }
        else
        {
            Uri my_contact_Uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.parseLong(contactId));
            photo_stream = ContactsContract.Contacts.openContactPhotoInputStream(getContentResolver(), my_contact_Uri);
        }
    
        if(photo_stream != null) 
        {
            BufferedInputStream buf =new BufferedInputStream(photo_stream);
            Bitmap my_btmp = BitmapFactory.decodeStream(buf);
            profile.setImageBitmap(my_btmp);
        }
        else
        {
            profile.setImageResource(R.drawable.contactpic);
        }
    
        cursor.close();
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
    {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    
    @Override
    public void onClick(View v) 
    {
        // TODO Auto-generated method stub
        if(v.getId() == answerButton.getId())
        {
            timerLayout.setVisibility(0);
    
            startTime = SystemClock.uptimeMillis();
            customHandler.postDelayed(updateTimerThread, 0);
    
            callType.clearAnimation();
    
            // Simulate a press of the headset button to pick up the call
            Intent buttonDown = new Intent(Intent.ACTION_MEDIA_BUTTON);     
            buttonDown.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK));
            this.sendOrderedBroadcast(buttonDown, "android.permission.CALL_PRIVILEGED");
    
            // froyo and beyond trigger on buttonUp instead of buttonDown
            Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON);       
            buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));
            this.sendOrderedBroadcast(buttonUp, "android.permission.CALL_PRIVILEGED"); 
        }
    
        if(v.getId() == rejectButton.getId())
        {
            RejectCall();
        }
    
    }
    
    private void RejectCall() 
    {
        TelephonyManager telephony = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
    
        try {
            // Java reflection to gain access to TelephonyManager's
            // ITelephony getter
            Class c = Class.forName(telephony.getClass().getName());
            Method m = c.getDeclaredMethod("getITelephony");
            m.setAccessible(true);
            com.android.internal.telephony.ITelephony telephonyService = (ITelephony) m.invoke(telephony);
            telephonyService.endCall();
            finish();
    
            timeSwapBuff += timeInMilliseconds;
            customHandler.removeCallbacks(updateTimerThread);
        }
        catch (Exception e) 
        {
            e.printStackTrace();
            Log.e("Error", "FATAL ERROR: could not connect to telephony subsystem");
            Log.e("Error", "Exception object: " + e);
        }
    }
    
    private Runnable updateTimerThread = new Runnable() 
    {
    
        public void run() 
        {
            timeInMilliseconds = SystemClock.uptimeMillis() - startTime;
            updatedTime = timeSwapBuff + timeInMilliseconds;
            int secs = (int) (updatedTime / 1000);
            int mins = secs / 60;
            int hours = mins / 60;
            secs = secs % 60;
            int milliseconds = (int) (updatedTime % 1000);
            timerValue.setText(""+ hours + ":" + String.format("%02d", mins) + ":"
                    + String.format("%02d", secs));
            customHandler.postDelayed(this, 0);
        }
    
    };
    
      }
    

1 个答案:

答案 0 :(得分:6)

对于拨打电话:我做了以下工作,并且工作正常。我创建了一个具有清单所需权限的传出接收器。

使用处理程序在延迟后调用活动。

像这样:

@Override
public void onReceive(Context context, Intent intent) 
{
    c = context;
    setResultData(null);
    phonenumber = getResultData();
    if (phonenumber == null)
    {
        phonenumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
    }
    setResultData(phonenumber);
    callActionHandler.postDelayed(runRingingActivity, 1000);
}


Handler callActionHandler = new Handler();
Runnable runRingingActivity = new Runnable() 
{
    @Override
    public void run() 
    {

        Intent intentPhoneCall = new Intent(c, OutgoingCallActivity.class);
        intentPhoneCall.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intentPhoneCall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        c.startActivity(intentPhoneCall);
    }
};

您可以使用电话号码将其发送到新活动。

如果您有任何疑问,请与我联系!