I am trying to implement custom incoming/outgoing calling screen. The following is what I have tried. U gave two problems
Sometime it calls the default incoming screen on my phone or sometimes it calls the customized screen. I would the phone always call customized screen.
I am not able to initiate calls for outgoing. the customized screen just comes up but doesn't make any calls.
How to solve this issue, I am not sure what is wrong here. It would be great if somebody can help me out fixing this..
Here is what I am trying:
Manifest:
<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: This has both incoming and outgoing
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 (For UI purpose - Incoming and outgoing):
@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);
}
};
}
To enable a template to replace your caller screen, tap on the + sign at the bottom as shown in the picture below. After you tap on the + sign, the caller screen template will show you a preview. This is exactly what your caller screen will look like when you get a call. You've two options on this screen.
In all cases, you have two choices: you can choose to have the phone ring and then manually decide whether you want to screen the call or not, or you can let Google automatically screen the call and decline it if it's a robocall.
You can follow these steps to set the video pop-up style for incoming calls on your Android device: Go to “ Home Screen.” Click on the “ Phone Dialer” icon. Open the screen for “ Mass Response.” Tap on the button for “Settings ” (you’ll find it on the screen’s lower right corner). Open “ Popup Menu.” Tap on “ Call Settings ” screen and open it.
Tap on “ Call Settings ” screen and open it. Scroll down and click on “ Other Call Settings.” Check the incoming calls screen-style status and confirm that it’s “ Classic.” To change it, click on “ Classic”; this opens up the prompt for “ Current Status .” Select “ Classic” and enable it.
This instantly takes you back to the screen for “Call Settings.” Change the style for “ incoming calls ” to “ Full-screen Caller Photo.” Now, call your Android device; your caller’s screen-style photo will display. Finally, “ Save” and “ activate” the contact on your device. Voila! You’re done; it’s now possible to recognize callers fantastically.
Check the incoming calls screen-style status and confirm that it’s “ Classic.” To change it, click on “ Classic”; this opens up the prompt for “ Current Status .” Select “ Classic” and enable it. This instantly takes you back to the screen for “Call Settings.”
For outgoing calls: I did the following as a work around and it is working fine. I created an outgoing receiver with all permissions required in manifest..
Called the Activity after a delay by using a handler.
Like this:
@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);
}
};
You can use the phone number to send it to the new activity.
Let me know if you have any questions!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With