Android: How to make a default dialer app?
Asked Answered
B

3

7

Today I got a rejection from Google for my app Facetocall

  • Your app does not appear to prompt the user to be a default handler prior to requesting related permissions as required by the policy. Please make necessary changes in order to comply with policy requirements and resubmit your app through a Declaration Form.

  • Default handler capability was listed on your declaration form, but your app has no default handler capability.

My goal is to make a default dialer app.

Here is my Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.gazman.beep"
    android:installLocation="preferExternal">

    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.READ_CALL_LOG" />
    <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
    <uses-permission android:name="android.permission.SEND_SMS" />
    ... and other permissions

    <application
        android:name=".application.BeepApp"
        android:allowBackup="false"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        tools:ignore="GoogleAppIndexingWarning">

        <activity
            android:name=".system_intents.IntentsActivity"
            android:launchMode="singleTask"
            android:noHistory="true"
            android:theme="@style/Theme.Transparent">
            <intent-filter>
                <action android:name="android.intent.action.DIAL" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.DIAL" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:scheme="tel" />
            </intent-filter>
        </activity>

        <activity
            android:name=".call.CallActivity"
            android:launchMode="singleTop"
            android:screenOrientation="portrait"
            android:showForAllUsers="true" />

        <service
            android:name="com.gazman.beep.call.MyInCallService"
            android:permission="android.permission.BIND_INCALL_SERVICE">
            <meta-data
                android:name="android.telecom.IN_CALL_SERVICE_UI"
                android:value="true" />
            <intent-filter>
                <action android:name="android.telecom.InCallService" />
            </intent-filter>
        </service>

        ... And other declarations

    </application>

</manifest>

And here is what I do when my app launches:

private void checkDefaultHandler() {
    if (isAlreadyDefaultDialer()) {
        return;
    }
    Intent intent = new Intent(TelecomManager.ACTION_CHANGE_DEFAULT_DIALER);
    intent.putExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME, getPackageName());
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(intent, REQUEST_CODE_SET_DEFAULT_DIALER);
    }
    else{
        throw new RuntimeException("Default phone functionality not found");
    }
}

private boolean isAlreadyDefaultDialer() {
    TelecomManager telecomManager = (TelecomManager) getSystemService(TELECOM_SERVICE);
    return getPackageName().equals(telecomManager.getDefaultDialerPackage());
}

What am I missing here?

I tried submitting the form again and this time I add a video that shows my app on an emulator(I see the same behavior on all the real devices too) here is the reply that I got back:

  • Your app does not appear to prompt the user to be a default handler prior to requesting related permissions as required by the policy. Please make necessary changes in order to comply with policy requirements and resubmit your app through a Declaration Form.
Bridgid answered 14/1, 2019 at 23:50 Comment(9)
Google recently announced that an application should not ask for SMS permission or call log permission if it is not a default SMS or CALL app. It did for security reasons. Find a link to the article here support.google.com/googleplay/android-developer/answer/9047303. In my opinion, because you want to behave as a default call app and use the above sensitive permissions, you must tell the user as to why u need these permissions and why he should allow you with the help of dialogue before proceeding to firing the startActivityForResult(intent, REQUEST_CODE_SET_DEFAULT_DIALER).Subgroup
@AbhishekMadan at the link that you sent me, click: Permitted uses of the SMS & Call Log Permissions, it will show my use case.Bridgid
If you believe your app meets the policy requirements for acceptable use or is eligible for an exception, submit a Permissions Declaration Form as soon as possible for Google Play to review. You will be notified if your request has been approved. You do not need to have implemented APK changes in order to submit the Declaration Form.. So, i believe you need to just submit the declaration form as they say.Subgroup
Yep I did and I got a rejection as mentioned in the questionBridgid
What they say is that your app should be the default handler before to ask and use the permissions. The point is what the app does before calling isAlreadyDefaultDialer(). Are you asking or using the permissions before being the default handler?Zacynthus
@EasyJoinDev No, I don't. Check out the video or download my app and you will see for yourself.Bridgid
@IlyaGazman Then they are wrong. We talk about the new procedure in reddit, join us redd.it/ak68l2Zacynthus
@IlyaGazman can you share some tips how to pass the review? I've already tried many submissions with all descriptions but still no success :(Beowulf
Did you find any solution?Phyto
E
1

to make default dialer app, you need to do 2 things :

1. add the following permissions in your android manifest

<activity>
    <intent-filter>
        <action android:name="android.intent.action.DIAL"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>
  1. actually performing the check :
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main_layout)
    ...
    checkDefaultDialer()
    ...
}
const val REQUEST_CODE_SET_DEFAULT_DIALER=200

private fun checkDefaultDialer() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
        return

    val telecomManager = getSystemService(TELECOM_SERVICE) as TelecomManager
    val isAlreadyDefaultDialer = packageName == telecomManager.defaultDialerPackage
    if (isAlreadyDefaultDialer)
        return
    val intent = Intent(TelecomManager.ACTION_CHANGE_DEFAULT_DIALER)
                .putExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME, packageName)
    startActivityForResult(intent, REQUEST_CODE_SET_DEFAULT_DIALER)
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    when (requestCode) {
        REQUEST_CODE_SET_DEFAULT_DIALER -> checkSetDefaultDialerResult(resultCode)
    }
}

private fun checkSetDefaultDialerResult(resultCode: Int) {
    val message = when (resultCode) {
        RESULT_OK       -> "User accepted request to become default dialer"
        RESULT_CANCELED -> "User declined request to become default dialer"
        else            -> "Unexpected result code $resultCode"
    }

    Toast.makeText(this, message, Toast.LENGTH_SHORT).show()

}
Educated answered 17/10, 2019 at 12:57 Comment(1)
Could you please tell me exactly what you did ?Educated
S
0

You don't need to panic. This kind of conversation happened with me also, regarding AdMob content on my app. I declared everything perfectly but still they were saying content rating not fine due to type of Ads my app was showing. When more mails exchanged they sent me screenshot with the proof of wrong Ads, so finally i checked my whole code again and found my mistake.

The point here is that Google is good at what they do, and if they said so, then your app lacks something.

To be very honest, your app did not ask the user anywhere to allow it to be set as default, instead it set itself default in the background. You should ask for every permission required by your app that are critical and can be used by any app or virus or spyware to interfere with user privacy.

You can do that with a function like in the following example, which is asking for Camera permission from the user:

private void requestCameraPermission() {
        Log.i(TAG, "CAMERA permission has NOT been granted. Requesting permission.");

        // BEGIN_INCLUDE(camera_permission_request)
        if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                Manifest.permission.CAMERA)) {
            // Provide an additional rationale to the user if the permission was not granted
            // and the user would benefit from additional context for the use of the permission.
            // For example if the user has previously denied the permission.
            Log.i(TAG,
                    "Displaying camera permission rationale to provide additional context.");
            Snackbar.make(mLayout, R.string.permission_camera_rationale,
                    Snackbar.LENGTH_INDEFINITE)
                    .setAction(R.string.ok, new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            ActivityCompat.requestPermissions(MainActivity.this,
                                    new String[]{Manifest.permission.CAMERA},
                                    REQUEST_CAMERA);
                        }
                    })
                    .show();
        } else {

            // Camera permission has not been granted yet. Request it directly.
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA},
                    REQUEST_CAMERA);
        }
        // END_INCLUDE(camera_permission_request)
    }

You can see the complete repository at Google Samples

And don't worry. If you rectify this problem, they will accept your application, as they did for mine.

Sabra answered 22/1, 2019 at 7:56 Comment(3)
"To be very honest, your apps did not ask user anywhere to allow it to be set as default" how did you riched this conclusion? Why are you saying apps while there is just one application that I am talking about? And how cam permission is relevant to the new policy?Bridgid
Well the code you post didn't have any query from the end user that's why. It should be in your checkdefaulthandler function before starting any intentSabra
The point here is that Google is good at what they do, and if they said so, then your app lacks something. well not always ;-)Zacynthus
I
-2

in case anyone comes cross this post . . . I used this for asking the user for changing the default dailer. Know that the there gonna be 2 windows prompting(for me it was fine).

   private void setDefaultDialer()


 {
    AlertDialog.Builder builder;
    builder = new AlertDialog.Builder(this);
    builder.setMessage("Do you want to make Cricket your default Dialer?(it will not cover or replace your dialer)")
            .setCancelable(false)
            .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    defaultDialerPackage = "cricket";
                    Intent intent = new Intent(TelecomManager.ACTION_CHANGE_DEFAULT_DIALER);
                    startActivityForResult(intent.putExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME,getPackageName()),REQUEST_CODE_SET_DEFAULT_DIALER);
                }
            })
            .setNegativeButton("No", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
                    Toast.makeText(getApplicationContext(),"Cancelled - No action was taken",
                            Toast.LENGTH_SHORT).show();
                }
            });

AlertDialog alert = builder.create();
alert.setTitle("Cricket need default dialer permission!!");
alert.show();

}

Imprescriptible answered 18/9, 2019 at 20:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.