How to get Android device Features using package manager - android

I am developing an android application and I need android device features. I know that, by using package manager, getSystemAvailableFeatures method should be available. Still the method is not available Can any one help me by post some example or source code related to that.

I use the following function to determine if a feature is available:
public final static boolean isFeatureAvailable(Context context, String feature) {
final PackageManager packageManager = context.getPackageManager();
final FeatureInfo[] featuresList = packageManager.getSystemAvailableFeatures();
for (FeatureInfo f : featuresList) {
if (f.name != null && f.name.equals(feature)) {
return true;
}
}
return false;
}
The usage (i.e from Activity class):
if (isFeatureAvailable(this, PackageManager.FEATURE_CAMERA)) {
...
}

If you know the feature you want to check then you don't need to enumerate all system features and check against the one you're looking for. Since API level 5 you can use the PackageManager.hasSystemFeature() function to do the same job as the isFeatureAvailable() function shown in the previous answer.
For example...
PackageManager packageManager = this.getPackageManager();
if (packageManager.hasSystemFeature(PackageManager.FEATURE_NFC))
Log.d("TEST", "NFC IS AVAILABLE\n");
else
Log.d("TEST", "NFC IS *NOT* AVAILABLE\n");

Related

How to get the phone Object in Oreo Aosp Code

I want to write Api for getdataroaming method which is already there in Aosp.
Just now I have written code like this.
ContentResolver cr=mPhone.getContext().getContentResolver();
if (Settings.Secure.getInt(cr.getContentResolver(),Settings.Secure.DATA_ROAMING) == 1) {
//Data Roaming Enabled
flag = true;
} else {
// Data Roaming Disabled
flag = false;
}
how to get the phone object in separate java file.
if I used the context.
From where i will get this context?

How to determine if any system dialog is displayed?

How to check if any system dialog (like the one below or USSD) is displayed in Android ?
Programmatic way or cmd root way?
Any variants.
You can theoretically do this using the AccessibilityService, but it is rather complicated and may or may not work on different devices. Users will need to manually enable accessibility features for your application. You can get callbacks from Android whenever any window is opened and you can then interrogate the window to determine if it has specific text in it or belongs to a specific package, etc. This is a "brute force" approach, but it can be useful in some situations.
A system dialog is an activity. You can detect it by the top activity class name using ActivityManager.
final ActivityManager manager = (ActivityManager) context
.getSystemService(Activity.ACTIVITY_SERVICE);
In devices with API Level less than 23 (M):
final List<ActivityManager.RunningTaskInfo> runningTasks = manager.getRunningTasks(1);
final ComponentName componentName = runningTasks.get(0).topActivity;
final String className = componentName.getClassName();
if (className.equals("YOUR_EXPECTED_ACTIVITY_CLASS_NAME")) {
// do something
}
In newer devices:
final List<ActivityManager.AppTask> appTasks = manager.getAppTasks();
final ComponentName componentName = appTasks.get(0).getTaskInfo().topActivity;
final String className = componentName.getClassName();
if (className.equals("YOUR_EXPECTED_ACTIVITY_CLASS_NAME")) {
// do something
}
Or in this case, you can check if the device is in airplane mode before starting the activity:
private boolean isAirplaneModeOn(final Context context) {
final int airplaneMode = Settings.System.getInt(
context.getContentResolver(),
Settings.System.AIRPLANE_MODE_ON,
0
);
return airplaneMode != 0;
}
...
if (!isAirplaneModeOn(this)) {
// do something
}
Your question made me think of a solution in use by the permissions management in Android 6+. Have you ever seen the error message if a Toast or system alert dialog opens up when trying to set permissions?
Android "Screen Overlay Detected" message if user is trying to grant a permission when a notification is showing
The way they did it is by overriding the dispatchTouchEvent method in Activity. This can check if anything is 'in the way' intercepting touch events. You can use your special Activity as a base class for any Activity in your app that you wish to detect any overlays on it.
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
mObscured = (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0;
return super.dispatchTouchEvent(event);
}
Add a public method to check at any given time if your activity is obscured
public boolean isObscured() {
return mObscured;
}
You should be careful - as it's not clear from the question - if a second Activity from a system or privileged app is at the front of the stack then your own activity will no longer be receiving touch events. This is to capture the fragments, toasts, floating widgets and other items that may share the view hierarchy.

What's the difference between "getApplicationLabel" and "loadLabel"?

Background
I'm working on my app that is an alternative to the app manager (link here), and wish to optimize it a bit.
As it turns out, one of the slowest things on the app is its bootup, and the main reason for this is getting the app name . I intend on caching it, but I also wish to optimize the way it's being queried, if possible.
The problem
Android has two ways to get the app name: PackageManager.getApplicationLabel and ApplicationInfo.loadLabel .
both have about the same description, but I'm not sure which one should be used.
Not only that, but looking at the code of "ApplicationInfo.loadLabel" , it looks something like this:
public CharSequence loadLabel(PackageManager pm) {
if (nonLocalizedLabel != null) {
return nonLocalizedLabel;
}
if (labelRes != 0) {
CharSequence label = pm.getText(packageName, labelRes, getApplicationInfo());
if (label != null) {
return label.toString().trim();
}
}
if (name != null) {
return name;
}
return packageName;
}
I can't find the code of "PackageManager.getApplicationLabel", as it's abstract.
The question
Is there any difference between the two?
If there is no difference, why do we have 2 very similar methods to get the same app name? I mean, I can use either of them only if I have both applicationInfo object and the PackageManager object, but that's enough to use any of the methods...
If there is difference, which of them is better in terms of speed?
The source of 'PackageManager.getApplicationLabel' is available in 'ApplicationPackageManager.java'. It is as follows;
#Override
public CharSequence getApplicationLabel(ApplicationInfo info) {
return info.loadLabel(this);
}
ApplicationPackageManager.java
I see in AppUtils.java the same wrapping is done as follows;
/** Returns the label for a given package. */
public static CharSequence getApplicationLabel(
PackageManager packageManager, String packageName) {
try {
final ApplicationInfo appInfo =
packageManager.getApplicationInfo(
packageName,
PackageManager.MATCH_DISABLED_COMPONENTS
| PackageManager.MATCH_ANY_USER);
return appInfo.loadLabel(packageManager);
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Unable to find info for package: " + packageName);
}
return null;
}

pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY) not giving corerct answer

I want to check if a device has any cameras before trying to open a qr code reader.
I have the following code:
public boolean checkDeviceCompatibility() {
PackageManager pm = context.getPackageManager();
if (pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) {
if (pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
return true;
} else {
// use front camera
Toast.makeText(
context,
"This device does not have a back camera so it has automatically reverted to the front camera",
Toast.LENGTH_SHORT).show();
return true;
}
} else {
util.displayErrorDialog(
context,
"This device does not have any cameras and therefore cannot make use of the QR Code feature.");
return false;
}
}
But now if I run this code in debug mode on my galaxy S3 with two cameras. the first if statement is returned false.
Why could this be?
FEATURE_CAMERA_ANY was added in Android 4.2. hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY) should return false for any pre-4.2 device. If your S3 is still on 4.1, that would explain your problem.
To make it clear.
FEATURE_CAMERA_ANY was added to Android 4.2 ( API-17): Android - developers.
code:
public static boolean hasCamera(Context context) {
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY);
}
Note that using this code will return false if device under version 4.2:
Then you should know that there is a bug with emulator when use FEATURE_CAMERA_ANY feature (with android 4.2 and above). see: Emulator does not honour Camera support flag
Thats why Im still using old way even its deprecated:
public static boolean hasCamera() {
return android.hardware.Camera.getNumberOfCameras() > 0;
}

Android UserManager: Check if user is owner (admin)

Im developing an app with the latest android version (4.2.1 API-Level 17) for tablets with multiuser capabilities.
I want to restrict certain features (like the access to the app preferences) to the owner of the tablet (that is the user who can add and remove other user accounts)
is there any way i can find out if the current user is the owner?
i read through the UserManager and UserHandle API docs but couldn't find a function that allows me to check for it.
have i missed something or is there another way to do that?
Similar but without reflection:
static boolean isAdminUser(Context context)
{
UserHandle uh = Process.myUserHandle();
UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
if(null != um)
{
long userSerialNumber = um.getSerialNumberForUser(uh);
Log.d(TAG, "userSerialNumber = " + userSerialNumber);
return 0 == userSerialNumber;
}
else
return false;
}
You can create an extension property in Kotlin to make it simpler:
val UserManager.isCurrentUserDeviceOwner: Boolean
get() = if (SDK_INT >= 23) isSystemUser
else if (SDK_INT >= 17) getSerialNumberForUser(Process.myUserHandle()) == 0L
else true
Then, using it is as simple as the following:
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
if (userManager.isCurrentUserDeviceOwner) TODO() else TODO()
You can further reduce boilerplate by using global system services definitions that makes userManager and other Android System Services available anywhere in your Kotlin code, with code included in this library I made: https://github.com/LouisCAD/Splitties/tree/master/systemservices
After researching further i found out that the multiuser api is not functional yet, it cant really be used for anything. there is a hack though for checking if the user is the owner using reflections:
public boolean isCurrentUserOwner(Context context)
{
try
{
Method getUserHandle = UserManager.class.getMethod("getUserHandle");
int userHandle = (Integer) getUserHandle.invoke(context.getSystemService(Context.USER_SERVICE));
return userHandle == 0;
}
catch (Exception ex)
{
return false;
}
}
This works for me on the Nexus 7 and Nexus 10 with Android 4.2.1
Its very dirty. so i wouldnt recommend using it unless you are making an app thats device and version specific

Categories

Resources