[Android Head-Units] sweetnothings:
ok lets look into it.

the problem is that our dialer does not like some characters which are commonly used to format phone numbers (at least when the activity to make the call is started) and google does always reformat the number on each time voice dialing. so edit the numbers on contacts did not help.

my solution was to implement a little wrapper to strip out the characters the dialer does not like.

in my case i have all numbers saved in the format of +41 99 999 99 99, after stripping all spaces it works. i think its very different on locale how google formats the number, so we need to experiment to get all problematic patterns.

the wrapper is simple: implementing an activity which propagates itself as default for calling, and then we can select it as default dialer on first use as with other apps. after stripping characters i start an intent of the joying dialer and pass the number.

so lets see the code.

activity part in manifest xml:

<activity android:name=".CallHandler" android:theme="@android:style/Theme.Translucent.NoTitleBar">
<intent-filter>
<action android:name="android.intent.action.CALL"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="tel"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.CALL_PRIVILEGED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="tel"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.DIAL"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="tel"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="tel"/>
</intent-filter>
</activity>

and the code of the activity:

import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

/**
* Created by sweetnothings on 02.10.2017.
*/
public class CallHandler extends Activity implements View.OnClickListener {
private EditText phoneField;
private final int permissionRequestId = 1001;
private final int activityRequestId = 1002;
private final String joyingBluetoothPackage = "com.syu.bt";
private final String joyingBluetoothApplication = "com.syu.app.PhoneActivity";
private final String callIntentCommand = "android.intent.action.CALL_PRIVILEGED";

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

setContentView(R.layout.activity_callhandler);
Intent intent = getIntent();
String phoneNumber = "";
phoneField = ((EditText) findViewById(R.id.editTextNumber));
Button bch = (Button) findViewById(R.id.buttonCall);
bch.setOnClickListener(this);
Button bc = (Button) findViewById(R.id.buttonCancel);
bc.setOnClickListener(this);

if(intent.getData()!=null) {
phoneNumber = intent.getData().toString();
}
if(phoneNumber == "" && intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER)!=null) {
phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
}
if(phoneNumber != "") {
phoneNumber = phoneNumber.replace("tel:", "").replace(" ", "").replace("-", "").replace(".", "").replace("(0)", "").replace("(", "").replace(")", "");
phoneField.setText(phoneNumber);
}
if(phoneNumber.length() > 8 && (phoneNumber.startsWith("+") || phoneNumber.startsWith("0"))) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, permissionRequestId);
} else {
makeCall(phoneField.getText().toString());
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case permissionRequestId: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Permission Phone Call granted.", Toast.LENGTH_SHORT).show();
makeCall(phoneField.getText().toString());
} else {
Toast.makeText(this, "Permission Phone Call denied!", Toast.LENGTH_LONG).show();
finish();
}
return;
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
finish();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.buttonCall:
EditText phoneField = (EditText) findViewById(R.id.editTextNumber);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, activityRequestId);
} else {
makeCall(phoneField.getText().toString());
}
break;
case R.id.buttonCancel:
finish();
break;
}
}

public void makeCall(String number) {
try {
Intent intent = new Intent(callIntentCommand);
intent.setClassName(joyingBluetoothPackage, joyingBluetoothApplication);
intent.setData(Uri.parse("tel:" + number));
startActivityForResult(intent, 1001);
} catch (Exception e) {
Toast.makeText(this, "Start of Joying BT App failed!", Toast.LENGTH_LONG).show();
}
}
}

and the activity xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#ccdddddd"
android:layoutMode="opticalBounds"
android:theme="@android:style/Theme.Translucent.NoTitleBar">
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="15sp"
android:id="@+id/linearLayoutTitle">

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Calling Phone Number:"
android:id="@+id/textViewTitle"
android:height="50sp"
android:textColor="@android:color/black"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true" />
</LinearLayout>

<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/linearLayoutControls"
android:background="#ccdddddd"
android:padding="15sp"
android:layout_below="@+id/linearLayoutTitle">

<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/editTextNumber"
android:minWidth="180sp"
android:layout_gravity="bottom|left"
android:textColor="@android:color/black" />

<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/linearLayoutButtons">

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Make Call"
android:id="@+id/buttonCall"
android:layout_gravity="bottom|right"
android:textColor="@android:color/black" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cancel"
android:id="@+id/buttonCancel"
android:textColor="@android:color/black"
android:layout_gravity="bottom|right" />
</LinearLayout>

</LinearLayout>

</RelativeLayout>

this is only quick and dirty coded as a proof of concept, i am sure it can be improved if someone of you is into coding android more than me :cool:

edit: one thing more, when google voice dial pops up with the contact to dial you can see the default app which is used, use the 3-dot menu button the change the default app, google saves the selection for future use.

edit 2: the solution works also to dial with contact apps like google contacts.

note: the code accepts international formated numbers only, if we like to accept short dial numbers we need to modify that part