As per documentation for app shortcuts
Rate Limiting
When using the setDynamicShortcuts(), addDynamicShortcuts(), or
updateShortcuts() methods, keep in mind that you might only be able to
call these methods a specific number of times in a background app, an
app with no activities or services currently in the foreground. In a
production environment, you can reset this rate limiting by bringing
your app to the foreground.
What is rate limiting in concern with app shortcuts? when isRateLimitingActive() should be used?
Looking at the source code it seems that the isRateLimitingActive() method returns false if you do not have any remaining calls left to the ShortcutManager API (hence the "0"). I guess rate limiting is needed because the API is resource intensive. I can imagine that at least the following will happen if you update a shortcut:
The launcher app (and other listeners) needs to be notified and starts updating it's UI or whatever is needed (depends on the launcher);
The system needs to store the new dynamic shortcut information;
You could use this method to find out if a call to setDynamicShortcuts(), addDynamicShortcuts() or updateShortcuts() will succeed before even trying to do so.
Source:
/**
* Return {#code true} when rate-limiting is active for the caller application.
*
* <p>See the class level javadoc for details.
*
* #throws IllegalStateException when the user is locked.
*/
public boolean isRateLimitingActive() {
try {
return mService.getRemainingCallCount(mContext.getPackageName(), injectMyUserId())
== 0;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
Bonus: setDynamicShortcuts(), addDynamicShortcuts() or updateShortcuts() return false if they did not succeed due to Rate Limiting.
The recommended maximum number of shortcuts is 4, although it is possible to publish up to 5. You can read more here.
Related
I'm implementing licensing in my Android App.
Why does LicenseCheckerCallback's method allow should return RETRY and NOT_LICENSED and dontAllow RETRY and LICENSED?
Accordingly to their method's name they shouldn't return nothing than respectively LICENSED and NOT_LICENSED/RETRY.
I must know how to properly handle the returned code in order to know if the user did download my App from Google Play.
The piece of script that return the code (int policyReason) is this:
private class MyLicenseCheckerCallback implements LicenseCheckerCallback {
public void allow(int policyReason) {
if (isFinishing()) {
// Don't update UI if Activity is finishing.
return;
}
// Should allow user access.
displayResult(getString(R.string.allow));
}
public void dontAllow(int policyReason) {
if (isFinishing()) {
// Don't update UI if Activity is finishing.
return;
}
displayResult(getString(R.string.dont_allow));
// Should not allow access. In most cases, the app should assume
// the user has access unless it encounters this. If it does,
// the app should inform the user of their unlicensed ways
// and then either shut down the app or limit the user to a
// restricted set of features.
// In this example, we show a dialog that takes the user to a deep
// link returned by the license checker.
// If the reason for the lack of license is that the service is
// unavailable or there is another problem, we display a
// retry button on the dialog and a different message.
displayDialog(policyReason == Policy.RETRY);
}
...
}
The LicenseCheckerCallback official documentation says:
public interface LicenseCheckerCallback {
/**
* Allow use. App should proceed as normal.
*
* #param reason Policy.LICENSED or Policy.RETRY typically. (although in
* theory the policy can return Policy.NOT_LICENSED here as well)
*/
public void allow(int reason);
/**
* Don't allow use. App should inform user and take appropriate action.
*
* #param reason Policy.NOT_LICENSED or Policy.RETRY. (although in theory
* the policy can return Policy.LICENSED here as well ---
* perhaps the call to the LVL took too long, for example)
*/
public void dontAllow(int reason);
...
}
Thanks a lot!
When you are creating an instance of LicenseChecker class, you must provide an implementation of Policy interface.
Policy used by {#link LicenseChecker} to determine whether a user should have access to the application.
Based on official documentation in the source code, the provided policy decides wheater a user can use the application or not.
Now suppose due to the network problems, the license checker could not connect to the server. In this case, you should have your own policy to allow the user to use the application or not. You can define your own custom policy by implementing the Policy interface or using one of the predefined StrictPolicy or ServerManagedPolicy policies.
Please look at the Table 2 here. As you see, if response code is one of the ERROR_CONTACTING_SERVER or ERROR_SERVER_FAILURE, then the reason will be RETRY but your provided policy will decide about allowing the user to use the application or not. Now, I think it should be clear why Policy.RETRY could be a potential input for the allow method.
As I mentioned before, you can provide your own custom policy. Suppose your user has the license to use your application but based on your policy you don't want to allow the user to use your application at that moment. In this case dontAllow method with Policy.LICENSED will call. On the other hand, suppose your user doesn't have the license to use your application but you like to allow him/her to use your application. In this case allow method with Policy.NOT_LICENSED will call.
I'm implementing Bio metric Prompt API for authorising user using Fingerprint. I found that Bio-metric Prompt API display different UI based on device sensor type.
Bio-metric API SDK call work independently to display respective UI based on sensor type.
Now the concern is:
In case of rear(at side of device in some devices) sensored device, it display dialog which also use to display error if any.
But in case of in/under display sensored device, it simply display a fingerprint impression and that does not display any error in case.
Now the question is:
Is there any API feature using that in-display prompt can display error.
In case not, how we can differentiate between both type of sensor device so can handle error explicitly.
In case you are still experiencing this problem, There is a recently published blog post that sheds some light on why the API behaves the way it does. The post also shows you how to use the API correctly.
You should only need to use the biometrics library in AndroidX.
Essentially you get three callbacks:
onAuthenticationSucceeded() is called when the user has been authenticated using a credential that the device recognizes.
onAuthenticationError() is called when an unrecoverable error occurs.
onAuthenticationFailed() is called when the user is rejected, for example when a non-enrolled fingerprint is placed on the sensor, but unlike with onAuthenticationError(), the user can continue trying to authenticate.
You can use any of these callbacks to post messages to your user through a Toast or such.
There is indeed an API and callback for you to utilize in this situation. The package you are looking for is either the Biometrics Package for API levels 28+ or the Fingerprint package for API levels 23-27.
The callback to which I am referring can be found here for API 28+ and here for API 23-27.
Here is some sample code with how the callback is initialized:
/**
* Helper class for authentication callback
*/
#RequiresApi(api = Build.VERSION_CODES.M)
private class FingerprintHandler extends FingerprintManager.AuthenticationCallback {
private FingerprintHandler(){}
/**
* Called when an unrecoverable error has been encountered and the operation is complete.
* No further callbacks will be made on this object.
* #param errMsgId An integer identifying the error message
* #param errString A human-readable error string that can be shown in UI
*/
#Override
public void onAuthenticationError(int errMsgId, CharSequence errString) {
//Authentication error. The 'errString' is meant to be displayed to the user
//Handle logic here
}
/**
* Called when a fingerprint is valid but not recognized.
*/
#Override
public void onAuthenticationFailed() {
//Authentication failed (Fingerprints don't match ones on device)
//Handle logic here
}
/**
* Called when a recoverable error has been encountered during authentication. The help
* string is provided to give the user guidance for what went wrong, such as
* "Sensor dirty, please clean it."
* #param helpMsgId An integer identifying the error message
* #param helpString A human-readable string that can be shown in UI
*/
#Override
public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
//Non-Fatal error (IE moved finger too quickly). The helpString can be displayed to the user to help them retry.
//Handle logic here
}
/**
* Called when a fingerprint is recognized.
* #param result An object containing authentication-related data
*/
#Override
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
//Authentication Succeeded. They are good to go and it matches the stored one
//Handle logic here
}
}
And here is some sample usage in a class of mine if the above code is not enough to get you moving.
With regards to utilizing an alert or display, I just use the callback info in conjunction with a Dialog or an on-screen textview if I don't want to block the screen.
I don't think your problem is something to do with In-display/Rear sensor. In my testing analyses with Biometricx APIs, I found both In-display/Rear sensor types showed error in the system UI when biometrics auth failed. It also depends on the device you are testing, device manufacturer may have decided not to support the Biometrics APIs. In my case, when I tested on Samsung S5 device, even though device had in-display sensor, canAuthenticate() returned false.
In Android, there's wake lock to keep the screen on. So, is there Mac equivalent to keep the screen on for a PC running Mac OS X? If that is the case, what are the APIs?
To add to it, there are also command-line tools, like the built-in caffeinate.
Yes, in OS X it is done at the OS level through IOPMLib, the Power Management subsystem, which is also the subsystem that controls AppNap under OS X Mavericks.
Here's an example of what we do when performing heavy calculations. In our case, we keep the CPU from sleeping, but you can prevent the display from sleeping by using kIOPMAssertionTypePreventUserIdleDisplaySleep where we used kIOPMAssertionTypePreventUserIdleSystemSleep.
#property IOPMAssertionID currentPowerAssertion;
- (void)assertPowerRequirement:(NSString*)reason
{
// don't re-assert if we're already here
if (_currentPowerAssertion)
return;
IOPMAssertionID assertionID;
IOReturn success = IOPMAssertionCreateWithName(
kIOPMAssertionTypePreventUserIdleSystemSleep, // prevent CPU from going to sleep
kIOPMAssertionLevelOn, // we are turning this on
(__bridge CFStringRef)reason, // here's why
&assertionID); // reference for de-asserting
if (success == kIOReturnSuccess) {
_currentPowerAssertion = assertionID;
} else {
NSLog(#"Power assert failed");
}
}
- (void)deassertPowerRequirement
{
if (!_currentPowerAssertion)
return;
IOReturn success = IOPMAssertionRelease(_currentPowerAssertion);
if (success !=kIOReturnSuccess) {
NSLog(#"Power de-assert failed");
}
_currentPowerAssertion = 0;
}
In this case, this is in our App delegate, and we have the currentPowerAssertion property to keep track. Since we only use one assertion state and only for one purpose, we use a single storage mechanism. However, you can assert multiple times from different parts of your program, as long as you balance the assertions with de-assertions and use appropriate reason. Specifications from Apple mandate a reason be given (not NULL), and suggest that the Application name and task be described in the assertion.
It's important to make sure that you de-assert when you don't need this any longer, although assertions are kept on a per-app basis, so when your App quits, they will automatically be de-asserted.
I posted this on Android dev group. I'm hoping I can get some feedback here.
The PhoneStateListener's callbacks onCellLocationChanged and onSignalStrengthsChanged were the goto methods for when I wanted to handle cell and signal data changes in GSM and CDMA. With API 17+, I can see that there's a new callback (onCellInfoChanged) for handling both cell and signal changes.
Looking at the documentation, it's not clear what I can expect from the introduction of this new callback.
Will LTE changes always and only trigger onCellInfoChanged?
Will GSM/CDMA changed remain on the older callbacks?
Does one overlap with the other? (i.e. Both old and new get triggered for LTE or GSM/CDMA.)
It may very well be that different OEMs will have different implementations (sigh!), but I'm hoping there are guidelines that everyone's supposed to follow.
Can anyone shed some light on this?
Thanks,
Sebouh
I didn't test if but it looks from the code that both will be called.
I downloaded code source of Android 4.3(API 18) using the SDK Manager.
The following observations made me think that both would be called.
The class that triggers these events is: com.android.server.TelephonyRegistry
It notifies the listener though:
public void listen(String pkgForDebug, IPhoneStateListener callback, int events, boolean notifyNow)
This same function calls for both type of notifications(Location and CellInfo) in a non exclusive way.
On line 256:
if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
try {
if (DBG_LOC) Slog.d(TAG, "listen: mCellLocation=" + mCellLocation);
r.callback.onCellLocationChanged(new Bundle(mCellLocation));
} catch (RemoteException ex) {
remove(r.binder);
}
}
This one will call onCellLocationChanged even on new LTE phone since there is nothing from the above code that would prevent this. This needs double checking that there is no upper layer that filters the events themselves
On line 300 in the same code:
if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) {
try {
if (DBG_LOC) Slog.d(TAG, "listen: mCellInfo=" + mCellInfo);
r.callback.onCellInfoChanged(mCellInfo);
} catch (RemoteException ex) {
remove(r.binder);
}
}
There are other things from the code that look like CDMA will be calling the newer API. For example com.android.internal.telephony.cdma.CdmaLteServiceStateTracker seems to be dealing with CDMA and LTE. Again it would require a more careful look but that should give you a good place to start.
You can also try to simulate that with the emulator.
This is for the Verizon LTE version of the Samsung Galaxy Nexus.
I am tasked with writing a tiny app that will effectively disable/enable 4G capability. This can be done manually via settings > mobile network > network mode and choosing either LTE/CDMA (4g enabled) or CDMA (3g only).
I have not tried anything yet because Android development isn't my strong suit. I am looking for guidance... examples, code samples etc. I am assuming this should almost be a one-liner, but it has been my experience that with Android development nothing is as simple as it appears.
Any help will be greatly appreciated.
There is a preference in the Settings.Secure class that is hidden from the SDK:
/**
* The preferred network mode 7 = Global
* 6 = EvDo only
* 5 = CDMA w/o EvDo
* 4 = CDMA / EvDo auto
* 3 = GSM / WCDMA auto
* 2 = WCDMA only
* 1 = GSM only
* 0 = GSM / WCDMA preferred
* #hide
*/
public static final String PREFERRED_NETWORK_MODE =
"preferred_network_mode";
You could use Reflection on this or just localize the constant to your project. The problem with this is that you cannot change the value of this setting (as with all secure settings), you can only read it. The aforementioned values are not the only possible ones, there are actually a few more located in com.android.internal.telephony.RILConstants, which is again hidden from the SDK and would require Reflection to access.
There is another hidden method in TelephonyManager, but again it is read only there is no other method for setting this constant. This would tell you exactly what you want to know, whether the device is set to "LTE/ CDMA" (LTE_ON_CDMA_TRUE) or "CDMA only" (LTE_ON_CDMA_FALSE):
/**
* Return if the current radio is LTE on CDMA. This
* is a tri-state return value as for a period of time
* the mode may be unknown.
*
* #return {#link Phone#LTE_ON_CDMA_UNKNOWN}, {#link Phone#LTE_ON_CDMA_FALSE}
* or {#link Phone#LTE_ON_CDMA_TRUE}
*
* #hide
*/
public int getLteOnCdmaMode() {
try {
return getITelephony().getLteOnCdmaMode();
} catch (RemoteException ex) {
// Assume no ICC card if remote exception which shouldn't happen
return Phone.LTE_ON_CDMA_UNKNOWN;
} catch (NullPointerException ex) {
// This could happen before phone restarts due to crashing
return Phone.LTE_ON_CDMA_UNKNOWN;
}
}
From my research you could not make such an application without root access and using something like setprop from the command line, but even then you may need to restart the entire Telephony process in order for this setting to take effect.
Finally, if you are still interested see com.android.phone.Settings to see how the system handles this toggle. It is rather elaborate, and as I mentioned would require permissions that a normal Android application would not be granted.
I'm also interested in changing the settings WCDMA-only, WCDMA/LTE, ...
I found the way to change Settings.secure.* with root privilege as is shown the below.
new ExecuteAsRootBase() {
#Override
protected ArrayList<String> getCommandsToExecute() {
ArrayList<String> cmds = new ArrayList<String>();
cmds.add("su -c 'chmod 755 "+mySqlite+"'");
cmds.add("echo \"UPDATE secure SET value='"+ value +"' WHERE name='"+ key +"'; \" | "+mySqlite+" /data/data/com.android.providers.settings/databases/settings.db");
//TODO: SQL injection can be done!!!
return cmds;
}
}.execute();
ExecuteAsRootBase is introduced here, and mySqlite is "/data/data/"+context.getPackageName()+"/files/sqlite3" where sqlite3 is put in advance.
However, it seems that we have to call com.android.internal.telephony.Phone.setPreferredNetworkType() for switching (WCDMA only<=>WCDMA/LTE) after setting Settings.secure.PREFERRED_NETWORK_MODE.
My phone (even set Settings.secure.PREFERRED_NETWORK_MODE = 2) attached to LTE network...
All the other answers are correct that this requires access to Settings.Secure. Take a look at how the phone app handles this setting https://github.com/dzo/packages_apps_phone/blob/master/src/com/android/phone/Use2GOnlyCheckBoxPreference.java
or take a look at the Toggle2G app source:
https://github.com/TheMasterBaron/Toggle-2G
http://developer.android.com/reference/android/provider/Settings.System.html
Aside from writing the code in your Activity.java, you will probably have to ask for permission to access these settings in the AndroidManifest.xml. So it's annoying but should be simple enough.