How to implement CallScreeningService for Andoid<=28 - java

**What I have done so far : **
I have implement it for Android SDK 29
RoleManager roleManager = (RoleManager) getSystemService(ROLE_SERVICE);
Intent intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_CALL_SCREENING);
startActivityForResult(intent, REQUEST_ID1);
**What I am looking for ? : **
I want to implement Call Screening Service for devices < SDK 29.
Kindly help me if anyone have done it before.

Unfortunately, you can't.
It is impossible to access the RoleManager class on Android versions < 29 because this class was introduced on Android 29. Therefore, you can only use this class on devices running Android 29 and up.

For Android <= 28, to bind the CallScreeningService the app must be set as the default dialer app. On runtime, a dialog can be displayed asking the user to set your app as the default dialer app as follows:
if (getSystemService(TelecomManager.class).getDefaultDialerPackage() != getPackageName()) {
Intent changedDialer= new Intent(TelecomManager.ACTION_CHANGE_DEFAULT_DIALER);
changedDialer.putExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME, getPackageName());
startActivity(ChangeDialer);
}

Related

How to launch an Activity from another Application in Android 30

I have been using the following code to open my other app from within my app. This code works upto Android 29 devices but this code does not work in Android 30 devices. Can somebody please help me make it work for Android 30 as well. Thanks
case R.id.btAudio:
Intent launchIntent = getPackageManager().getLaunchIntentForPackage(getString("com.android.audioapp"));
Intent uin = new Intent(MainActivity.this, AudioInstall.class);
if (launchIntent != null) {
startActivity(launchIntent);
} else {
startActivity(uin);
}
this.finish();
break;
Android 11 added restrictions regarding the visibility of other apps. Apps that have targetSdk set to >= 30 can't interact with and open other apps without specifying this in the manifest.
To specify that your app interacts with another specific app, you need to add a <queries> element to your manifest file:
<manifest package="com.example.game">
<queries>
<package android:name="com.android.audioapp" />
</queries>
...
</manifest>
The link below contains other examples in case you need to specify a broader range of apps which you want to interact with.
Source: https://developer.android.com/training/basics/intents/package-visibility

Programmatically open 'About device' page in Settings correctly?

startActivity(new Intent(android.provider.Settings.ACTION_DEVICE_INFO_SETTINGS)); opens this page in Samsung devices:
However, I want it to open this page like the rest of Android devices, how can I do it?
As Pedro Antonio said:
If it doesn't work for SAMSUNG devices I'm afraid it will probably not be possible. At least with no official answer. Many times vendors modify stock Android so for SAMSUNG devices settings app is different than stock AOSP, and the official method will not work.
When we call:
Intent i = new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS);
startActivity(i);
we are referring to activity com.android.settings.Settings$DeviceInfoSettingsActivity and in logs we can see that activity is started
2020-06-26 11:33:43.804 4838-5126/? I/ActivityManager: START u0 {act=null typ=null flg=0x8000 cmp=ComponentInfo{com.android.settings/com.android.settings.Settings$DeviceInfoSettingsActivity}} from uid 1000
On devices like Huawei P10, Software Information data is part of DeviceInfoSettingsActivity. After some digging i found out that on Samsung S7 device Software Information is Fragment that is called inside DeviceInfoSettingsActivity
2020-06-26 11:44:25.780 7103-9703/? D/Settings: packageName : com.android.settings className : com.android.settings.SubSettings
2020-06-26 11:44:25.812 7103-7103/? D/SubSettings: Launching fragment com.samsung.android.settings.deviceinfo.SoftwareInfoSettings
I am not sure is it possible to access DeviceInfoSettingsActivity code (I couldn't) and see if you can send some extra data to open specific Fragment. So at this point i do not believe that it is possible to launch that specific fragment from intent.
The main point is it seems impossible. Let's look at what is the reason.
The DeviceInfoSettingsActivity can be opened by an intent call like:
Intent intent = new Intent(android.provider.Settings.ACTION_DEVICE_INFO_SETTINGS);
startActivity(intent);
or
Intent intent = new Intent();
intent.setClassName(
"com.android.settings",
"com.android.settings.Settings$DeviceInfoSettingsActivity"
);
startActivity(intent)
As you can see here:
https://android.googlesource.com/platform/packages/apps/Settings/+/master/src/com/android/settings/Settings.java
Settings and all of its inner classes are children of SettingsActivity. By taking a look at source code of SettingsActivity, we found out it is possible to show a sub-settings, passing the fragment name as an intent extra with key ":settings:show_fragment" to the SettingsActivity:
SettingsActivity#onCreate() then SettingsActivity#launchSettingFragment()
If we dig into logs where the target screen is shown, we'd see that the target fragment name is com.samsung.android.settings.deviceinfo.SoftwareInfoSettings.
But the problem is that there is a check on fragment names at SettingsActivity#isValidFragment() which allows specific fragments to navigate to and they are SettingsGateway#ENTRY_FRAGMENTS:
protected boolean isValidFragment(String fragmentName) {
// Almost all fragments are wrapped in this,
// except for a few that have their own activities.
for (int i = 0; i < SettingsGateway.ENTRY_FRAGMENTS.length; i++) {
if (SettingsGateway.ENTRY_FRAGMENTS[i].equals(fragmentName)) return true;
}
return false;
}
The alternative for showing other fragments in settings is to open SubSettings activity which overrides the isValidFragment to accepts every fragment.
#Override
protected boolean isValidFragment(String fragmentName) {
Log.d("SubSettings", "Launching fragment " + fragmentName);
return true;
}
That is exactly what happens when the SoftwareInfoSettings is shown:
D/Settings: packageName : com.android.settings className : com.android.settings.SubSettings
D/SubSettings: Launching fragment com.samsung.android.settings.deviceinfo.SoftwareInfoSettings
Unfortunately, starting the SubSettings from uid except launcher's uid isn't possible, because it is not an exported activity to be visible from the outside:
AndroidManifest.xml:
<activity android:name=".SubSettings"
android:parentActivityName="Settings"
android:theme="#style/Theme.SubSettings"/>
If you try to run:
Intent intent = new Intent();
intent.setClassName(
"com.android.settings",
"com.android.settings.SubSettings"
);
intent.putExtra(
":settings:show_fragment",
"com.samsung.android.settings.deviceinfo.SoftwareInfoSettings"
);
startActivity(intent);
will see this error log:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.aminography.settingsapp, PID: 14566
java.lang.SecurityException: Permission Denial:
starting Intent { flg=0x10000000 cmp=com.android.settings/.SubSettings (has extras) }
from ProcessRecord{fac1d09 14566:com.aminography.settingsapp/u0a104} (pid=14566, uid=10104)
not exported from uid 1000
Unfortunately, since isValidFragment() and SettingsGateway#ENTRY_FRAGMENTS are parts of the platform, not your application's runtime, it's impossible to change them even with reflection.
As the android documentation says, you should use
Intent i = new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS);
startActivity(i);
https://developer.android.com/reference/android/provider/Settings#ACTION_DEVICE_INFO_SETTINGS
If it doesn't work for SAMSUNG devices I'm afraid it will probably not be possible. At least with no official answer. Many times vendors modify stock Android so for SAMSUNG devices settings app is different than stock AOSP, and the official method will not work.

How to resolve setWifiEnabled(bool) deprecated method into Android Q?

In my case, I have existing code for enabling wifi. Here I am getting code depreciation at CONNECTIVITY_ACTION and setWifiEnabled(true) in Android Q api level 29. Below code is working fine in old version but depreciation happen only on api 29. How to resolve it with help of version condition.
Enable Wifi Code
private void enableWifi(Context context, String ssid) {
if(webWifiStateListener != null) {
context.unregisterReceiver(webWifiStateListener);
}
webWifiStateListener = new WifiStateListener(ssid);
context.registerReceiver(webWifiStateListener,
new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); // CONNECTIVITY_ACTION Deprecated Android Q
webWifiManager.setWifiEnabled(true); // Deprecated Android Q
}
Android Q won't let apps turn Wi-Fi on and off. You can use something like this https://developer.android.com/reference/android/provider/Settings.Panel
Use this in Android Q:
Intent panelIntent = new Intent(Android.Provider.Settings.Panel.ActionWifi);
StartActivityForResult(panelIntent,1);
Don't use:
webWifiManager.setWifiEnabled(true); // Deprecated Android Q

Java Android - Redmi 3 (MIUI) - Notification icons cannot be changed?

I'm trying to change notification icons and in emulator it is OK :
This is what I want (tested on emulator API level 22 (android 5.1.1)) BUT, when i'm running this APP in my real phone (Xiaomi Redmi 3 prime with MIUI 8.0.1) also android 5.1.1 - the notifications looks very very very differant. This notification icons does not showing (just a default application icon).
But... why? What can i do now?
Here is my code:
NotificationCompat.Builder b = new NotificationCompat.Builder(compat);
b.setSmallIcon((state == STATE_STOPPED) ? R.drawable.ic_stat_remove : R.drawable.check);
b.setContentText(content);
b.setContentTitle(BASE_NOTIFICATION_TITLE);
b.setOngoing(true);
b.setAutoCancel(true);
b.setColor((state == STATE_STOPPED) ? Color.RED : Color.rgb(22, 219, 28));
NotificationManager m = (NotificationManager) compat.getSystemService(NOTIFICATION_SERVICE);
m.notify(0, b.build());
Just a very simple notification... can someone tell me, what's wrong? Or just MIUI turns off all notification icons and set it to default app launch icons?
Thanks!
EDIT: notification in my phone looks like this...
I had the same problem, but Juan Pablo (in comment Java Android - Redmi 3 (MIUI) - Notification icons cannot be changed?) gave me a clue and now I have a solution:
//notification is an object of class android.app.Notification
try {
Class miuiNotificationClass = Class.forName("android.app.MiuiNotification");
Object miuiNotification = miuiNotificationClass.newInstance();
Field field = miuiNotification.getClass().getDeclaredField("customizedIcon");
field.setAccessible(true);
field.set(miuiNotification, true);
field = notification.getClass().getField("extraNotification");
field.setAccessible(true);
field.set(notification, miuiNotification);
} catch (Exception e) {
}
Now it works as it is expected.
This is behavior of MIUI system. You can not display different icons in notification, by default it takes app icon as notification icon.

How does Facebook add badge numbers on app icon in Android?

I know there are several Qs here that ask if its possible to add badges to an android app and they all end up with a NO answer...
But somehow the latest Facebook beta version for Android seems to do something which at least look like a badge even if it is not technically exactly that.
In that post one of the commenters says that it is somehow related to TouchWiz.
And also here they mention it as a feature of the "S3 TouchWiz Jelly Bean Addon".
I still would appreciate information on how does this can be done and if there is some API for this that I can use in my own app (when running in an appropriate environment - i.e. the same device where FB demonstrates this behavior) ?
Hi you can use this lib simply.
Support : Sony,Samsung,LG,HTC,Xiaomi,ASUS,ADW,APEX,NOVA,Huawei,ZUK,OPPO
ShortcutBadger
Add :
int badgeCount = 1;
ShortcutBadger.applyCount(context, badgeCount);
Remove :
ShortcutBadger.applyCount(context, 0);
I have figured out how this is done for Sony devices.
I've blogged about it here. I've also posted a seperate SO question about this here.
Sony devices use a class named BadgeReciever.
Declare the com.sonyericsson.home.permission.BROADCAST_BADGE permission in your manifest file:
Broadcast an Intent to the BadgeReceiver:
Intent intent = new Intent();
intent.setAction("com.sonyericsson.home.action.UPDATE_BADGE");
intent.putExtra("com.sonyericsson.home.intent.extra.badge.ACTIVITY_NAME", "com.yourdomain.yourapp.MainActivity");
intent.putExtra("com.sonyericsson.home.intent.extra.badge.SHOW_MESSAGE", true);
intent.putExtra("com.sonyericsson.home.intent.extra.badge.MESSAGE", "99");
intent.putExtra("com.sonyericsson.home.intent.extra.badge.PACKAGE_NAME", "com.yourdomain.yourapp");
sendBroadcast(intent);
Done. Once this Intent is broadcast the launcher should show a badge on your application icon.
To remove the badge again, simply send a new broadcast, this time with SHOW_MESSAGE set to false:
intent.putExtra("com.sonyericsson.home.intent.extra.badge.SHOW_MESSAGE", false);
I've excluded details on how I found this to keep the answer short, but it's all available in the blog. Might be an interesting read for someone.
There is not a standard way to achieve this; Many makers such as Sony or Samsung have implemented it in their own Android customization.
For example in Samsung, you have to broadcast an intent with BADGE_COUNT_UPDATE action, let MainActivity be your main activity class and count be the number you want to display in your app icon, note that 0 will hide the badge:
Intent intent = new Intent("android.intent.action.BADGE_COUNT_UPDATE");
intent.putExtra("badge_count", count);
intent.putExtra("badge_count_package_name", context.getPackageName());
intent.putExtra("badge_count_class_name", MainActivity.class.getName());
context.sendBroadcast(intent);
Sony devices uses "com.sonyericsson.home.action.UPDATE_BADGE" action with their custom extras as #Marcus Answered, so you have to add "com.sonyericsson.home.permission.BROADCAST_BADGE" permission to your app manifest and:
Intent intent = new Intent("com.sonyericsson.home.action.UPDATE_BADGE");
intent.putExtra("com.sonyericsson.home.intent.extra.badge.ACTIVITY_NAME", MainActivity.class.getName());
intent.putExtra("com.sonyericsson.home.intent.extra.badge.SHOW_MESSAGE", true);
intent.putExtra("com.sonyericsson.home.intent.extra.badge.MESSAGE", String.valueOf(count));
intent.putExtra("com.sonyericsson.home.intent.extra.badge.PACKAGE_NAME", context.getPackageName());
context.sendBroadcast(intent);
Note: it's desirable to query your app's data (context.getPackageName(), MainActivity.class.getName()) rather than hardcode it just in case you do some refactoring in the future.
But somehow the latest Facebook beta version for android does just that...
Not according to the forum thread that contains the screenshot that you linked to. Quoting vakama94:
Well, that's actually TouchWiz and not just the app. I have a Galaxy S II running JellyBean 4.1.2 and it makes the same thing but with some other applications
Whether Samsung has a public API to allow apps to publish numbers to be used as badges, I cannot say. This could be something that they did privately with a few firms.
You are welcome to provide evidence of seeing these badges on a stock Android home screen, such as one of the Nexus series devices.
I answer to this assuming that some flutter dev can search this...
In Flutter, you can achieve this by using
Flutter app badger library.
It is as simple as
FlutterAppBadger.updateBadgeCount(1); // show
FlutterAppBadger.removeBadge(); // hide

Categories

Resources