Can a third-party app implement CallScreeningService in android 7? - android

Android API level 24 introduces a new Service called the CallScreeningService. The documentation says that the service can by implemented by the default dialer to screen incoming calls. I would like to implement this service in my own app, preferably without creating an entire dialer app, but a simple naive implementation seems to be ignored by the OS when an incoming call happens.
AndroidManifest.xml snippet:
<service android:name="com.example.callbouncer.CallService" android:permission="android.permission.BIND_SCREENING_SERVICE">
<intent-filter>
<action android:name="android.telecom.CallScreeningService"/>
</intent-filter>
</service>
CallService.java:
// imports...
public class CallService extends CallScreeningService {
#Override
public void onScreenCall(Call.Details callDetails) {
CallResponse.Builder response = new CallResponse.Builder();
Log.e("CallBouncer", "Call screening service triggered");
respondToCall(callDetails, response.build() );
}
}
There are no errors while building or installing this program, but the screening doesn't seem to be taking place. Have I done something wrong (like the manifest or missing implementations/overrides in the service) or is it just not possible? If it's not possible in a small app like this, will it be possible if I implement an entire dialing app and set it as the default dialer? Finally, if that's the case, is there anything preventing me from just forking the dialer out of the AOSP and adding my features to it?

As of Android 10 (API 29+), you can have a CallScreeningService without the requirement of also implementing an entire dialer app. Until Android 10, only the default dialer app's call CallScreeningService would be invoked.
https://developer.android.com/about/versions/10/features#call-screening
Don't get too excited though, because it's very buggy and does not work as the documentation says it does:
CallScreeningService#onScreenCall is called for known contacts
CallScreeningService#setSkipCallLog doesn't show blocked calls in the call log
My workaround for getting called for known contacts was to ask the user for contact access and check if the incoming caller was in the user's contacts. There is no workaround for the other issues at the moment.
I made a very basic screening app that declines all calls from numbers not in the user's contacts you can use an an example if you like: https://github.com/joshfriend/gofccyourself

Looking at the docs you linked to:
This service can be implemented by the default dialer (see
getDefaultDialerPackage()) to allow or disallow incoming calls before
they are shown to a user.
Don't think you can do this in a separate app (at least with the current interface: I'd expect in the not too distant feature it will be exposed).

Related

How to cancel any/all work manager request if the app is removed directly from app tray?

I'm trying to use Android WorkManager in an application in order to schedule some background task. The requirement is to cancel the API request when the app is removed directly from app-tray.
I'm able to detect if app is getting removed from app-tray, by using Service class -> onTaskRemoved method. And here I'm making the WorkManager API cancel request.
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Log.d("onTaskRemoved","onTaskRemoved called");
WorkManager.getInstance().cancelAllWork();
}
This is working fine as expected. Please suggest if there is any other better alternative to achieve it.
For some android devices (for some vendors) they implemented like if any apps is removed from app tray means they will force stop the app.So the services,work manager are also stopped.
For some other android devices (for some
other vendors) they implemented like if any apps is removed from app tray means they will stop/kill only the current activity of the app & not force stop the app.So the services,work manager are not stopped.
First you need to check your target devices is comes in which category.
If you need to do this, I think you're probably using the wrong tool. WorkManager is specifically for requests that need to persist and execute at some point. Consider using an Executor or coroutine instead.

Android DeviceAdminReceiver: onNetworkLogsAvailable intent never received

UPDATE
I'm noticing that I actually am receiving the NETWORK_LOGS_AVAILABLE intent! The problem is, it's taking a very long time (over an hour?) to receive it.
Is there any known way to increase the frequency of receiving these events?
Original Question
I am trying to process DNS events that can now be read after receiving the onNetworkLogsAvailable intent in a DeviceAdminReceiver application. This functionality was made available as of Android 8.0.
For some reason, I am never receiving this intent, even though I am successfully calling the setNetworkLoggingEnabled method. Upon admin being enabled, I am receiving the ACTION_DEVICE_ADMIN_ENABLED event, but nothing else after that.
Here's where I enable network logging:
public class NetworkAdminReceiver extends DeviceAdminReceiver {
#Override
public void onEnabled(Context context, Intent intent) {
DevicePolicyManager manager =
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
if ( manager == null )
{
throw new IllegalStateException("Unable to get DevicePolicyManager");
}
if (manager.isDeviceOwnerApp(context.getPackageName())) {
manager.setNetworkLoggingEnabled(getWho(context), true);
}
else
{
Toast.makeText(context, "This application is not device owner. DNS logging only works" +
" when this application is setup as the Device Owner", Toast.LENGTH_LONG).show();
}
}
// *snip* rest of class
}
Although I am not sure whether it's required (cannot find in documentation), I've also added the NETWORK_LOGS_AVAILABLE intent action to the receiver's filter:
<receiver android:name=".admin.NetworkAdminReceiver"
android:label="#string/device_admin"
android:description="#string/device_admin_description"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data android:name="android.app.device_admin"
android:resource="#xml/device_admin" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED"/>
<action android:name="android.app.action.NETWORK_LOGS_AVAILABLE"/>
</intent-filter>
</receiver>
The application is marked as the device owner, network logging is enabled, and yet I never receive the intent. The only explanation I could think of is that network logs do not become available very frequently, but I could find no documentation supporting this theory.
I am also currently only testing this in the emulator. I am unsure if that would have an effect on this, though I cannot see how it would.
Is there anything that I am missing in order to properly receive the network logs via the DeviceAdminReceiver?
I'm afraid there's no elegant solution.
This limitation looks like it was made intentionally. As you can see in the sources, the event is triggered when hard-coded thresholds are reached. It's either 1200 events or 1.5H timeout, whichever comes first. I did not manage to find any usable hooks in the NetworkLogger. They definitely did not want users to meddle with it.
The only option I see is to use reflection to get access to the hidden API.
The most straightforward, IMHO, is to get a handle to the IIpConnectivityMetrics service and use it to subscribe to the network events. I did not test this solution myself, though.
It seems like you can now force retrieve log for debugging purposes as described here: https://developer.android.com/work/dpc/logging#development_and_testing
Quote from the documentation:
While you’re developing and testing, you might want to receive onNetworkLogsAvailable() callbacks without having to browse hundreds of web pages. In Android 9.0 (API level 28) or higher, you can make a few sample network requests and force the system to send a logs-available callback. Run the following Android Debug Bridge (adb) command in your terminal:
adb shell dpm force-network-logs
The system limits how frequently you can use the tool and reports any intentional slowing in the terminal output. If there aren’t any logs to retrieve, your DPC doesn’t receive a callback.

Is it possible to Catch incoming Phone Number? Using Cordova

This is primarily for my Work place so having an app running all the time is not an issue.
The question How do i attach a hook to activate the App or background process when a call is made, and can it retrieve the phone number?
All the App has to do is send a request with the phone number to a server in-house
The reason for the question:
I am toying with the idea of creating a Support Service module which can give the Service worker a better grasp of the problem at hand.
Consider this:
Customer calls the company's support line
Service worker picks up phone
The computer looks up the Customers phone number on the Company's database and gives the Service Worker every detail they have on the customer ( Issues created, Website, Basic Info )
The biggest problem i can see is how do i Catch the number coming from the phone?
Looking up a customer via their phone number is not the issue.
Alternatively the Service worker will have to manually enter the phone number, but would be a nice feature to do it automatically.
Yes, You will need a BroadcastReceiver and have to override
#Override
protected void onIncomingCallReceived(Context ctx, String number, Date start)
{
//
}
Also insert permissions in Manifest.xml . If you want compatibility over oreo use runtime permissions for those permissions

Answer incoming call using android.telecom and InCallService

Since API 21, Google has been adding features to android.telecom in general, especially by implementing more members of TelecomManager and the addition of InCallService. This last one is is supposed to allow non-system, 3rd-party apps to provide and replace the functionality of the system Calls app in-call screen - the Window that pops up and allows action on EXTRA_STATE_OFFHOOK or EXTRA_STATE_RINGING broadcasts (i.e. incoming and outgoing phone calls).
Currently, only this screen has full control of ringing and active calls and associated system callbacks with fine-grained information, by means of the root-restricted MODIFY_PHONE_STATE permission and a lot of secured AOSP code not even accessible by reflection. It's notably one of the most changed pieces of code in different manufacturers' ROM flavours, together with the launcher, contacts and camera.
This is all very pretty but...
How do you actually develop a 3rd-party InCallService?
Namely:
How do you get notified about, and acquire instances of GSM Calls
How does one answer these calls
What is the life-cycle of the callbacks on this class
Does Google provide any actual tutorial for this that I haven't found
I won't ask answers for all of these at once, but any one answer probably associates to the other questions. This is broad but intrinsically it needs to be: there's no example on the web I've stumbled upon other than AOSP-code, and that code is based on the assumption of root-privileges, which makes it unusable for 3rd-party app development purposes.
How do you get notified about, and acquire instances of GSM Calls
First, the user will need to select your app as the default Phone app. Refer to Replacing default Phone app on Android 6 and 7 with InCallService for a way to do that.
You also need to define an InCallService implementation the system will bind to and notify you about the call:
<service
android:name=".CallService"
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>
There you should handle at least onCallAdded (set up listeners on Call, start your UI - activity - for the call) and onCallRemoved (remove listeners).
How does one answer these calls
If the user wants to answer the call, you need to invoke the method Call#answer(int) with VideoProfile.STATE_AUDIO_ONLY for example.
What is the life-cycle of the callbacks on this class
Check out Call.Callback for events that can happen with a single call.
Does Google provide any actual tutorial for this that I haven't found
I don't know about Google, but you can check out my simplified example https://github.com/arekolek/simple-phone
Follow the advice from the second comment of Replacing in call app. In addition you need a service that implements the InCallService interface. When a call arrives the onCallAdded(Call call) method will be called, giving you a reference to the call object.
<service
android:name=".InCallServiceImplementation"
android:enabled="true"
android:exported="true"
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>
Once you have the call object, answering it's as simple as call.answer(). I suggest that when you get the stuff above working, run a couple of test calls to get to know when the different callbacks are invoked.
Regarding tutorials, I couldn't find any when I was looking into this, but that was over a year ago...
Hope this helps!
I guess Google must've read this question, because apparently on Android 8, a new permission finally allows answering calls through a 3rd party dev-facing permission.
android.permission.ANSWER_PHONE_CALLS (...) allows apps to answer
incoming phone calls programmatically
No details yet though, since the documentation for API 26 hasn't been released yet. I'll make sure to update this answer when they do.
EDIT: user arekolek provided an answer that works perfectly on the original API version of this question (at the time of asking, API was 23, even though the question mentions API 21), thus he gets the tick for right answer. Refer to his answer if you want to implement an incall screen that targets minimum SDK of 23. Note you might need API-dependant code or compat library tweaks if you want it to work on more recent APIs that deprecate (or restrict) usage of the provided sample code. the github repo works as I initially intended.
I would recommend you to see this project to build a dialer app for Android.
https://github.com/HiddenPirates/Dialer

How to prevent SMS going to inbox in Android Kitkat

In previous versions of android we could block SMS by using following code:
<receiver android:name=".broadcastreceivers.OnSMSReceived"
android:exported="true" android:permission="android.permission.BROADCAST_SMS">
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
and in broadcast receiver, abortBroadcast() function prevent SMS from going to inbox.
But this method is not working in kitkat as, from Kitkat SMS will only be received by default SMS app. Is there any workaround to create SMS blocker app in kitkat?
You should read this page: http://android-developers.blogspot.com/2013/10/getting-your-sms-apps-ready-for-kitkat.html
A change was introduced in KitKat that only allows one application at a time (the default SMS app) to have write permissions on the SMS DB and to be able to consume it.
You have 2 ways of solving your problem:
Follow Google advice on how to request the user to switch the default SMS application to your application during the time when you need to perform your changes (and once you finish doing it, allow the user to switch back to the original default SMS app).
Find a temporary hacky way to do what you need to do. As a hint, there is a hidden API: AppOpsManager#setMode that you could potentially exploit in order to give your application write permissions (OP_WRITE_SMS), head over to this XDA page to learn more about it: http://forum.xda-developers.com/showthread.php?t=2551072
Needless to say, any hacky solution is just temporary as a private/hidden API could change at any moment. It is strongly encouraged to implement what Google advised us to implement which again is described here.
you can check that your application is a default SMS application or not. for this purpose see this link. you can get the package name of default SMS app and check with your name, if equal with each other then you can block SMS with Delete from inbox. this should be worked for you.
I know this is an old question, but here's a possible solution to KitKat SMS blocking:
http://superdupersms.com/
Since it isn't a technical solution but rather a product based solution, it's possible this should be a comment and not an "answer" - and I am involved in the development.
But I haven't found any other solution that allows other apps to interact with the SMS database like they did prior to KitKat - which directly addresses the question. This solution allows a non-default SMS app to block SMS.

Categories

Resources