I use SignalStength to get the quality of the signal, before sending sms:
signalStrength.getLevel()
I then wanted to compare the integer with a static constant in SignalStength:
if (signalStrengthLevel == SignalStrength.SIGNAL_STRENGTH_POOR) {
//...
}
But it doesn't compile in Android Studio. I realized that for some reason, these constants are marked as hidden in the source code:
/** #hide */
public static final int SIGNAL_STRENGTH_POOR
= TelephonyProtoEnums.SIGNAL_STRENGTH_POOR; // = 1
Which forces me to copy/paste these constants in one of my own classes...
I then wonder if anyone knows the reason why the developers decided to mark these constants as hidden?
In the documentation of the TelephonyManager, we can find getSignalStrength() method, which returns SignalStrength type, which has getLevel() method. In the documentation of getLevel() method, we can read the following information about returned integer value:
a single integer from 0 to 4 representing the general signal quality.
This may take into account many different radio technology inputs. 0
represents very poor signal strength while 4 represents a very strong
signal strength.
Taking that into consideration, I'd solve that in the following way:
create static values like:
private final static int VERY_POOR_SIGNAL = 0;
private final static int POOR_SIGNAL = 1;
private final static int MEDIUM_SIGNAL = 2;
private final static int STRONG_SIGNAL = 3;
private final static int VERY_STRONG_SIGNAL = 4;
and use this values to compare them with the integer value returned by:
telephonyManager.getSignalStrength().getLevel()
The word /** #hide */ just informs that the API is not accessible from SDK. I think it might be for security reasons.
Check this post
Related
I'm trying to build a profile for the Tasker app that responds to the BATTERY_CHANGED broadcast intent and I saw one of the Extras called Online that appears to correspond with the specific charger type or condition, but I can't seem to find a proper list of potential values for this Extra. At best, I've found a few of the values, such as 1 being None, 4 is USB, 10 is Wireless, 100 is Fast Wireless. Others I have just guessed at, such as 6 being a QuickCharge 2.0 or 3.0 type charger and 19 being a Power Delivery charger, but otherwise I can't be sure.
Is there any official documentation for this Extra in Android P?
There's surprisingly little documentation about the online extra!
I found this list which seems to be from a decompiled Samsung Pay app, weirdly enough:
public static final int BATTERY_ONLINE_FAST_WIRELESS_CHARGER = 100;
public static final int BATTERY_ONLINE_INCOMPATIBLE_CHARGER = 0;
public static final int BATTERY_ONLINE_NONE = 1;
public static final int BATTERY_ONLINE_POGO = 23;
public static final int BATTERY_ONLINE_TA = 3;
public static final int BATTERY_ONLINE_USB = 4;
public static final int BATTERY_ONLINE_WATER_IN_CONNECTOR = 101;
public static final int BATTERY_ONLINE_WIRELESS_CHARGER = 10;
The values seem to match with almost all of yours, I do find it very odd that seems to be no other record of them (from a quick Google).
Despite the android.os package of the linked file, perhaps it's not part of the OS / has been changed / has a different name. Maybe a Samsung-specific feature?
How do you add 3 or more complications in your watch face? Does the name of the complication ids matter? I know how to have 2 complications,https://codelabs.developers.google.com/codelabs/adding-complications-to-your-android-wear-watch-face/index.html#0, but not 3 or 4.
Is this correct?:
private static final int LEFT_DIAL_COMPLICATION = 0;
private static final int RIGHT_DIAL_COMPLICATION = 1;
private static final int BOTTOM_DIAL_COMPLICATION = 2;
public static final int[] COMPLICATION_IDS = {LEFT_DIAL_COMPLICATION, RIGHT_DIAL_COMPLICATION, BOTTOM_DIAL_COMPLICATION};
Or do I have to change that code? I haven't found any documentations on 3 complications or more.
Thanks for any answer!
(Posted solution on behalf of the OP).
The name wasn't the problem, it was a name-array.
I came across the code here. Can someone explain to what is Menu.First and why +1? I couldn't find it in the Android developer document.
private static final int MENU_ADD = Menu.FIRST;
private static final int MENU_LIST = MENU.FIRST + 1;
private static final int MENU_REFRESH = MENU.FIRST + 2;
private static final int MENU_LOGIN = MENU.FIRST + 3;
In the context of the accepted answer referenced in your comments, the poster is simply using these values as id's for dynamically added menu items so that clicks can be registered in inOptionsItemSelected().
For example, say you wanted to add a new button to your menu dynamically that turned the screen blue, you might create a constant value called MENU_TURN_SCREEN_BLUE. This would store an arbitrary number which you can later use as an id. For example (keeping in mind Menu.FIRST = 1:
private static final int MENU_TURN_SCREEN_BLUE = Menu.FIRST + 60;
or
private static final int MENU_TURN_SCREEN_BLUE = 69084;
Are both valid. Now, when you add a new item to a menu with the add() method, you can use this value:
menu.add(0, TURN_SCREEN_BLUE, 0, "Press To Turn Screen Blue");
You could of course just write the number in directly, but constant are helpful (amongst other reasons) for avoiding bugs in your code that arise from accidentally typing in the wrong number.
Keep in mind though that there are other ways to generate unique id's - see this question for details.
Refer this documentation
FIRST Refers to
First value for group and item identifier integers.
It is a constant value
Constant Value: 1 (0x00000001)
Refer this link
I am creating in my app bunch of programmatic Views. As it appeared to be they all by default have the same id=-1. In order to work with them I need to generate unique id's.
I have tried several approaches - random number generation and based on current time, but anyway there's no 100% guarantee that different Views will have different id's
Just wondering is there any more reliable way to generate unique ones? Probably there's special method/class?
Just want to add to Kaj's answer, from API level 17, you can call
View.generateViewId()
then use the View.setId(int) method.
In case you need it for targets lower than level 17, here is its internal implementation in View.java you can use directly in your project:
private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
/**
* Generate a value suitable for use in {#link #setId(int)}.
* This value will not collide with ID values generated at build time by aapt for R.id.
*
* #return a generated ID value
*/
public static int generateViewId() {
for (;;) {
final int result = sNextGeneratedId.get();
// aapt-generated IDs have the high byte nonzero; clamp to the range under that.
int newValue = result + 1;
if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
if (sNextGeneratedId.compareAndSet(result, newValue)) {
return result;
}
}
}
ID number larger than 0x00FFFFFF is reserved for static views defined in the /res xml files. (Most likely 0x7f****** from the R.java in my projects.)
From the code, somehow Android doesn't want you to use 0 as a view's id, and it needs to be flipped before 0x01000000 to avoid the conflits with static resource IDs.
Just an addition to the answer of #phantomlimb,
while View.generateViewId() require API Level >= 17,
this tool is compatibe with all API.
according to current API Level,
it decide weather using system API or not.
so you can use ViewIdGenerator.generateViewId() and View.generateViewId() in the
same time and don't worry about getting same id
import java.util.concurrent.atomic.AtomicInteger;
import android.annotation.SuppressLint;
import android.os.Build;
import android.view.View;
/**
* {#link View#generateViewId()}要求API Level >= 17,而本工具类可兼容所有API Level
* <p>
* 自动判断当前API Level,并优先调用{#link View#generateViewId()},即使本工具类与{#link View#generateViewId()}
* 混用,也能保证生成的Id唯一
* <p>
* =============
* <p>
* while {#link View#generateViewId()} require API Level >= 17, this tool is compatibe with all API.
* <p>
* according to current API Level, it decide weather using system API or not.<br>
* so you can use {#link ViewIdGenerator#generateViewId()} and {#link View#generateViewId()} in the
* same time and don't worry about getting same id
*
* #author fantouchx#gmail.com
*/
public class ViewIdGenerator {
private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
#SuppressLint("NewApi")
public static int generateViewId() {
if (Build.VERSION.SDK_INT < 17) {
for (;;) {
final int result = sNextGeneratedId.get();
// aapt-generated IDs have the high byte nonzero; clamp to the range under that.
int newValue = result + 1;
if (newValue > 0x00FFFFFF)
newValue = 1; // Roll over to 1, not 0.
if (sNextGeneratedId.compareAndSet(result, newValue)) {
return result;
}
}
} else {
return View.generateViewId();
}
}
}
Since support library 27.1.0 there's generateViewId() in ViewCompat
ViewCompat.generateViewId()
Create a singleton class, that has an atomic Integer. Bump the integer, and return the value when you need a view id.
The id will be unique during the execution of your process, but wil reset when your process is restarted.
public class ViewId {
private static ViewId INSTANCE = new ViewId();
private AtomicInteger seq;
private ViewId() {
seq = new AtomicInteger(0);
}
public int getUniqueId() {
return seq.incrementAndGet();
}
public static ViewId getInstance() {
return INSTANCE;
}
}
Note that the id might not be unique, if there already are views that have ids in the view 'graph'. You could try to start with a number that is Integer.MAX_VALUE, and decrease it instead of going from 1 -> MAX_VALUE
Regarding the fallback solution for API<17, I see that suggested solutions start generating IDs starting from 0 or 1. The View class has another instance of generator, and also starts counting from number one, which will result in both your and View's generator generating the same IDs, and you will end up having different Views with same IDs in your View hierarchy. Unfortunately there is no a good solution for this but it's a hack that should be well documented:
public class AndroidUtils {
/**
* Unique view id generator, like the one used in {#link View} class for view id generation.
* Since we can't access the generator within the {#link View} class before API 17, we create
* the same generator here. This creates a problem of two generator instances not knowing about
* each other, and we need to take care that one does not generate the id already generated by other one.
*
* We know that all integers higher than 16 777 215 are reserved for aapt-generated identifiers
* (source: {#link View#generateViewId()}, so we make sure to never generate a value that big.
* We also know that generator within the {#link View} class starts at 1.
* We set our generator to start counting at 15 000 000. This gives us enough space
* (15 000 000 - 16 777 215), while making sure that generated IDs are unique, unless View generates
* more than 15M IDs, which should never happen.
*/
private static final AtomicInteger viewIdGenerator = new AtomicInteger(15000000);
/**
* Generate a value suitable for use in {#link View#setId(int)}.
* This value will not collide with ID values generated at build time by aapt for R.id.
*
* #return a generated ID value
*/
public static int generateViewId() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
return generateUniqueViewId();
} else {
return View.generateViewId();
}
}
private static int generateUniqueViewId() {
while (true) {
final int result = viewIdGenerator.get();
// aapt-generated IDs have the high byte nonzero; clamp to the range under that.
int newValue = result + 1;
if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
if (viewIdGenerator.compareAndSet(result, newValue)) {
return result;
}
}
}
}
just looking through the source for renderscript.
I think I spotted a mistake, on line 36
private static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
Think that needs to be a double == but don't have enough coding experience to be sure.
No, I don't think it is a bug. It's setting LOG_ENABLED to either LOGD or LOGV depending on the value of DEBUG.
The relevant bit is:
public class RenderScript {
static final String LOG_TAG = "libRS_jni";
private static final boolean DEBUG = false;
#SuppressWarnings({"UnusedDeclaration", "deprecation"})
private static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
and that last line is conceptually equivalent to:
private static final boolean LOG_ENABLED;
if (DEBUG)
LOG_ENABLED = Config.LOGD;
else
LOG_ENABLED = Config.LOGV;
In fact,
private static final boolean LOG_ENABLED == DEBUG ? Config.LOGD : Config.LOGV;
doesn't actually make sense since it means:
private static final boolean ((LOG_ENABLED == DEBUG)
? Config.LOGD
: Config.LOGV);
which doesn't have a variable name being declared at all, just a value that should be assigned to something.
It's just a simple bit of confusion about how ternary operators work in Java. You're doing something like:
int i;
boolean b;
int n1=2;
int n2=3;
i = b ? n1 : n2;
where b can be an expression evaluating to true or false. I used to use parenthesis around the first element to make this clear, although I just looked through some of my code and I seem to have stopped doing that now!