I have a problem identifying the data roaming setting in Android L. In previous versions of Android, I was able to access either Settings.Secure or Settings.Global (depending on the Android version), and get the setting.
But now, on Android L, this no longer works. Whether data roaming is on or off, the return from the Settings.Global is always 0.
Android L supports multi SIM out of the box, so, a new manager was created to handle this: SubscriptionManager. This subscription manager, handles the several settings of the several SIM cards in the form of SubInfoRecord classes. I can retrieve the settings per SIM card.
However, the dataRoaming filed inside that class is always 0 as well.
Does anyone know how can this be achieved on the new API?
My app is a system app that comes embedded in the phones from factory so, I should be able to access all the APIs available.
However, I've spent a long time looking in the source code but I found nothing. In the Settings.Global class there's no indication that that setting no longer works on Android.
Does anyone have a clue on where this setting was moved to?
Thanks in advance!
Check this DevicePolicyManager.setGlobalSetting
as from documentation this can only be called by device owner app.
Is your app is installed as device owner ?
If not you can check the following links
Create device owner without root
Create device owner with root
Do something like this
DevicePolicyManager manager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
manager.setGlobalSetting(<Admin_Component>, Settings.Global.DATA_ROAMING, <value>);
Admin_Component: Component instance
Value: "0" for disable or "1" for enable
Since android 5.0, android supports multiple SIM cards, use the following code to check for data roaming.
public static boolean isDataRoamingEnabled(Context context) {
SubscriptionManager subMngr = (SubscriptionManager) context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
int id = SubscriptionManager.getDefaultDataSubscriptionId();
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
return false;
}
SubscriptionInfo ino = subMngr.getActiveSubscriptionInfo(id);
if (ino == null)
return false;
return ino.getDataRoaming() == 1;
}
Related
I've been searching on this for quite some time, and have found lots of solutions that ultimately use the Android GUI to prompt the end-user for connection/confirmation. We would like to present a user with a form and directly connect to the specified network. I understand from a security perspective why this is necessary, but in our case, it is a system app going on a fully managed Android device. It is not intended for general use in the Play store. We are using Xamarin, but I can adapt any Java/Kotlin code.
The closest I've found thus far is the following (using C#):
public void ConnectToWifi(string ssid, string password = "") {
var wifiNetworkSpecifier = new WifiNetworkSpecifier.Builder().SetSsid(ssid);
if (!string.IsNullOrEmpty(password))
wifiNetworkSpecifier.SetWpa2Passphrase(password);
var networkRequest = new NetworkRequest.Builder().AddTransportType(TransportType.Wifi)?
.SetNetworkSpecifier(wifiNetworkSpecifier.Build())?.Build();
if (networkRequest is null)
return;
var theNetworkCallback = new TheNetworkCallback();
var connectivityManager = (ConnectivityManager?)MainActivity.Current.ApplicationContext?
.GetSystemService(Context.ConnectivityService);
connectivityManager?.RequestNetwork(networkRequest, theNetworkCallback);
}
It sorta works, but does prompt the end-user, and my understanding, this approach is deprecated and doesn't work well in newer versions of Android. We're hoping for a solution that works in Android 11.
I'm even fine if there's a solution to write directly to wifi files on the OS. I've seen various solutions to manually populate entries via ADB, but I'm having a tough time adapting that to Xamarin/Java (can't seem to access the /data/misc/wifi directories). Again, this is intended for use exclusively on our own managed devices.
I have a blog post about this topic here: https://blog.ostebaronen.dk/2020/11/android-11-wifi.html
Android Network API is not the greatest thing to work with as there are pitfals depending on the API level the code runs on.
From Android 10 and up a lot of the Network stuff has been restricted for "privacy" reasons, so you cannot work around not asking the user for input, unless the device is rooted or your App is set up as Device Admin.
For Android 11, there is a new API to present a system dialog and allow the user to save and connect to a network. This will look something like:
You can launch this through an Intent called android.settings.WIFI_ADD_NETWORKS:
var intent = new Intent(
"android.settings.WIFI_ADD_NETWORKS");
var bundle = new Bundle();
bundle.PutParcelableArrayList(
"android.provider.extra.WIFI_NETWORK_LIST",
new List<IParcelable>
{
new WifiNetworkSuggestion.Builder()
.SetSsid(ssid)
.SetWpa2Passphrase(password)
.Build()
});
intent.PutExtras(bundle);
StartActivityForResult(intent, AddWifiSettingsRequestCode);
You can then get the result in your Activity overriding OnActivityResult and fetching the result like so:
if (requestCode == AddWifiSettingsRequestCode)
{
if (data != null && data.HasExtra(
"android.provider.extra.WIFI_NETWORK_RESULT_LIST"))
{
var extras =
data.GetIntegerArrayListExtra(
"android.provider.extra.WIFI_NETWORK_RESULT_LIST")
?.Select(i => i.IntValue()).ToArray() ?? new int[0];
if (extras.Length > 0)
{
var ok = extras
.Select(GetResultFromCode)
.All(r => r == Result.Ok);
// if ok is true, BINGO!
return;
}
}
}
I have a repository here with the full sample: https://github.com/Cheesebaron/Android11WiFi
From using this in the wild, I've found that this API does not work nicely with some OEMs such as OnePlus and Huawei. Some of these either restrict or the System Settings App simply crashes due to a misconfiguration on their part. For those I fall back to the API's introduced in Android 10.
How can I differentiate between a TV and a STB/game console on AndroidTV programatically? This method (https://developer.android.com/training/tv/start/hardware) won't work because an STB running AndroidTV is considered a television.
What's Your Goal?
The obvious reason for doing this would be to determine if a device is suitable for a game to be played on. If it's for any other reason, then the purpose needs to be elaborated on in order to receive applicable assistance.
With that said ...
Since it's not possible to query the device type directly -- personally, I'd look for something that only a game console would be likely to have.
In other words: a game controller/gamepad.
public ArrayList<Integer> getGameControllerIds() {
ArrayList<Integer> gameControllerDeviceIds = new ArrayList<Integer>();
int[] deviceIds = InputDevice.getDeviceIds();
for (int deviceId : deviceIds) {
InputDevice dev = InputDevice.getDevice(deviceId);
int sources = dev.getSources();
// Verify that the device has gamepad buttons, control sticks, or both.
if (((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD)
|| ((sources & InputDevice.SOURCE_JOYSTICK)
== InputDevice.SOURCE_JOYSTICK)) {
// This device is a game controller. Store its device ID.
if (!gameControllerDeviceIds.contains(deviceId)) {
gameControllerDeviceIds.add(deviceId);
}
}
}
return gameControllerDeviceIds;
}
Of course, it's not fool-proof. Obviously, nothing would be returned if the gamepad(s) were unplugged at the time (not sure when that would happen). Not to mention, some TVs support gamepads (Samsung comes to mind first) -- but, if you're intention is to verify that there's an adequate input available for the application, this would be ideal.
If a gamepad isn't present, a message could be displayed stating, "Please connect a gamepad." -- while continuously checking in the background, and automatically proceeding once one is detected.
I want to implement a listview showing android applications with their internet usage. Fir this, first i have to list all the apps, i have done this using PackageManager, like this:
packageManager = getPackageManager();
List<PackageInfo> packageList = packageManager
.getInstalledPackages(PackageManager.GET_META_DATA);
apkList = (ListView) findViewById(R.id.applist);
apkList.setAdapter(new ApkAdapter(this, packageList, packageManager));
But this code lists all system apps as well like : Android Sytem, Calculator,Calender, Status Bar, Live Wallpapers etc. which doesnt look appropriate. I tried to filter system apps using:
/*To filter out System apps*/
for(PackageInfo pi : packageList) {
boolean b = isSystemPackage(pi);
if(!b) {
packageList1.add(pi);
}
}
But then the code displays only installed apps, like whatsapp, tango, foursquare etc. It does not show apps like gmail, facebook, browser,maps.
Can anybody suggest how should i write the code that only displays list of application that actually use the internet. Thanks in advance!
I want to implement a listview showing android applications with their
internet usage.
An anybody suggest how should i write the code that only displays list
of application that actually use the internet
One solution (maybe only one that works best and came to my head) is to use TrafficStats class that calculating data (TCP, UDP) transferred through network. Exactly in your case, you need to get data for each UID (each application has own UID).
All what you need to know if application trasfered more that zero bytes through network and when you know that, you can tell that "this application uses network".
Here is pseudo-code you could use:
List<Application> collection = new ArrayList<Application>();
Application app = null; // some custom object is good approach
PackageManager pm = getActivity().getPackageManager();
for (ApplicationInfo info: pm.getInstalledApplications(
PackageManager.GET_META_DATA)) {
// received data by application
long downloaded = TrafficStats.getUidRxBytes(info.uid);
// transmitted data by application
long uploaded = TrafficStats.getUidTxBytes(info.uid);
// filter system applications only
if ((info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
// check if application has network usage
if (downloaded > 0 || uploaded > 0) {
// it's application you want
}
}
// non-system application
else {
if (downloaded > 0 || uploaded > 0) {
// it's application you want
}
}
}
It's important to say that TrafficStats is available from API 8 and also Before JELLY_BEAN_MR2, this may return unsupported on devices where statistics aren't available. I used this approach and never had a problems.
Note: Also I want to mention that maybe there are another possible approach(es) for example reading from some system files but this is (at least for me) hardcoded approach and i don't recommend to use it (also in various devices files can be on different places, have different content and different filename).
I hope it will help you solve your problem.
Application use internet will need Internet Permission
You can filter out those app by checked PackageInfo.permission
The issue is that I need to install an apk(non market app) and for this, the user need to activate the unknown source setting, so i send him (if he didn't have it activated) to the settings so he can turn on the option, the issue is that i tested it in different phones and in samsung that option is on applications while in htcs phones is on security. i want send the user to that option but i don't know how to do it
I read about this and no one knows exactly how to do it
this is my code
int canInstallFromOtherSources = Settings.Secure.getInt(ctx2,Settings.Secure.INSTALL_NON_MARKET_APPS);
if(canInstallFromOtherSources == 0)
{
Intent intentSettings = new Intent();
intentSettings.setAction(android.provider.Settings.ACTION_APPLICATION_SETTINGS);
startActivity(intentSettings);
}
You can do it with the following line (changing to the corresponding action):
startActivityForResult(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS), REQUEST_CODE_ENABLE_LOCATION_PROVIDERS);
Check Android Settings documentation.
I think you should use ACTION_SECURITY_SETTINGS and one of ACTION_APPLICATION_SETTINGS or ACTION_APPLICATION_DEVELOPMENT_SETTINGS.
And here (line 304), you've got a working example of one of my apps: Tureame
I want to detect whether two SIM cards are there in my dual-SIM android phone programmatically. I found one API (TelephonyManager.getSIMState()), but it is for normal single-SIM phones. Are there any APIs to detect whether or not two SIMs are inserted in my dual-SIM phone?
Android does not support multiple SIMs, at least from the SDK. Device manufacturers who have created multi-SIM devices are doing so on their own. You are welcome to contact your device manufacturer and see if they have an SDK add-on or something that allows you to access the second SIM.
Edit: (15th July, 2015)
Since API 22, you can check for multiple SIMs using SubscriptionManager's method getActiveSubscriptionInfoList(). More details on Android Docs.
From now, if the phone is MTK powered one, you can use TelephonyManagerEx class from MediaTek SDK.
Take a look at the docs.
final SubscriptionManager subscriptionManager = SubscriptionManager.from(getApplicationContext());
final List<SubscriptionInfo> activeSubscriptionInfoList = subscriptionManager.getActiveSubscriptionInfoList();
int simCount = activeSubscriptionInfoList.size();
btnBack.setText(simCount+" Sim available");
Log.d("MainActivity: ","simCount:" +simCount);
for (SubscriptionInfo subscriptionInfo : activeSubscriptionInfoList) {
Log.d("MainActivity: ","iccId :"+ subscriptionInfo.getIccId()+" , name : "+ subscriptionInfo.getDisplayName());
}
Well, this is not fool proof. But if you have two SIMs which are on two different network operators you can try something like this:
PhoneServiceStateListener listener = new PhoneServiceStateListener(this);
tm.listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE);
.
.
.
class PhoneServiceStateListener extends PhoneStateListener {
Context context = null;
public PhoneServiceStateListener(Context context) {
this.context = context;
}
public PhoneServiceStateListener() {
}
#Override
public void onServiceStateChanged(ServiceState serviceState) {
if (serviceState.getState() == ServiceState.STATE_IN_SERVICE) {
//You get this event when your SIM is in service.
//If you get this event twice, chances are more that your phone is Dual SIM.
//Alternatively, you can toggle Flight Mode programmatically twice so
//that you'll get service state changed event.
}
super.onServiceStateChanged(serviceState);
}
}
Ideally you'll get SIM service state changed event for both the SIMs and then you can check for network operator name or something like that to check if you have two SIM cards. But you need to have two SIM cards running on two different networks.