Using mock data in eclipse which doesn't produce warnings - android

How can I create a layout file with data and fill them with some example data so that I can see what I have done without producing warnings.
Here is an example:
If I remove the text (which wants Android Lint) I have a plain blue screen, which is not helpful at all.
By the way this is the warning:
[I18N] Hardcoded string "Foobar", should use #string resource example.xml /Example/res/layout Line 42 Android Lint Problem

Create an entry in your strings.xml for each of your example Strings.
On the other hand, this is a Lint warning. You can safely ignore this without causing immediate harm to your app, as these are only meant to guide you in best practices.
Go to the Eclipse preferences, into the Android submenu, then into the Lint Error Checking menu and disable the HardcodedText warning.
Second Method
Instead of setting the example text through XML, use the setText() through Java code, and enclose it in an if condition as follows:
if(BuildConfig.DEBUG) {
view.setText("My example text");
}
BuildConfig.DEBUG was added in ADT 17, and is true whenever you do a debug build. When you export the apk, it is set to false. As the variable is set to false and never reassigned, the Java compiler will optimize your code and remove these statements. They will not be compiled into a production app.

Related

How to allow hard coded strings and stop asking about using strings.xml

I'm working currently on an android project and I have no plans in mind whatsoever to translate it to other languages, so I'm not saving string literals in strings.xml. However Android Studio keeps complaining everytime I hard code a string literal especially when setting the text value for a TextView.
Is there a way to disable these warnings?
you can edit it in the following location Settings->Editor->Inspections->Android Lint->TextView Internationalization:
and for the xml Settings->Editor->Inspections->Android Lint->Hardcoded Text:
The best way to do this in my opinion is to use a gradle file, this will allow you to suppress these globally without having to do it in Android Studio, so your settings can go into source control as well, and then you don't have to individually decorate each method you want to apply the warning to. To do this, disable SetTextI18n in your gradle files lint options as follows:
android {
lintOptions{
disable 'SetTextI18n'
}
}
Gradle sync and voila, warnings gone.
Add
#SuppressLint("SetTextI18n")
on top of your function(s).
Example:
#SuppressLint("SetTextI18n")
private void updateEZWBMode2ConnectionStatus(){
switch (IsConnected.checkMode2(mContext)){
case IsConnected.USB_TETHERING:
M2StatusTV.setText("Status: Connected");
M2StatusTV.setTextColor(Color.argb(255,0,255,0));
M2ReceiveTV.setVisibility(View.VISIBLE);
startTestReceiverSafe(M2ReceiveTV);
break;
case IsConnected.USB_CONNECTED:
M2StatusTV.setText("Status: No Tethering");
M2StatusTV.setTextColor(Color.argb(255,255,51,51));
M1ReceiveTV.setVisibility(View.GONE);
M2ReceiveTV.setVisibility(View.GONE);
stopTestReceiverSafe();
break;
case IsConnected.USB_NOTHING:
M2StatusTV.setText("Status: No USB Connection");
M2StatusTV.setTextColor(Color.argb(255,255,51,51));
M1ReceiveTV.setVisibility(View.GONE);
M2ReceiveTV.setVisibility(View.GONE);
stopTestReceiverSafe();
break;
}
}
Old question, but anyway the accepted answer is misleading.
There is no need to translate string literal resources. In fact, they can be marked as non-translatable in the resources file. This way, you'll still adhere to best practices while not being annoyed by lint and translations.
<string name="invite_sent" translatable="false">Invite sent</string>
While disabling Lint my be useful to stop being annoyed, there is a further reason you want to (and should) use string literal resources: repetition. Following the DRY (Don't Repeat Yourself) principle can avoid a miriad of problems down the line, from complex refactors to unexpected behaviour, as well as inconsistency in the user(s) experience while using the app. Just imagine that an "Ok" button is present in 10+ screens. Having a single reference and source simplifies and centralizes maintenance of the project.

Break on variable value change in Android Studio 1.1.0?

I know I could set a breakpoint at every line where my code changes the variable, but is there an option such as right-clicking a variable (to "Add to Watches") that would stop when a variable changes value?
I think C++ has this option. See this.
And Eclipse? See this.
Is this implemented in AS?
You can break on value changes of some variables in Android Studio 1.1.0.
Android Studio calls them 'Java Field Watchpoints'.
From the breakpoints windows, (Run -> "View breakpoints...") or Ctrl+Shift+F8,
you can add "Java Field Watchpoints" from the plus in the top left corner, and then select your class and variable.
If the goal is simply to set a watchpoint where execution halts if a variable's value changes, there are two methods:
Pressing Ctrl-shift-F8 to set a watchpoint brings up this dialog:
That looks more powerful but it's confusing because it lacks the option I need; and there's an extra step: filling in the dialog box below:
Once you fill it in correctly, you get the same options for stopping execution as in the simpler method below:
Define the variable on one line ending with a semicolon.
Left-click in the area where you set a normal breakpoint and up pops a dialog box.
Choose options to suit your needs.
Any instance where the value of the variable prefDbExists changes, execution will pause as at any "normal" (unconditional) breakpoint. And that's all I needed when I asked the original question.
EDIT: Fully qualified class name is {package name}.{class name})
What you seek for is commonly known as "WatchPoint".
You will find detailed answer and examples on the doc. page of JetBrains - IntelliJ - Idea which is the basis for Android Studio.
https://www.jetbrains.com/help/idea/2016.3/creating-field-watchpoints.html
For me this works perfectly !
Add a Kotlin Field Watchpoint by clicking on the space next to the line number for the field declaration in Android Studio. Select Kotlin Field Watchpoint from the Set Breakpoint menu. You will now get a breakpoint whenever that value changes.

Variable initialization inside enum, or preventing enum with missing cases in compile time

I have a problem with a variable that is being initialized inside a switch over an enum. It seems that Android Studio (and Eclipse) is ignoring the fact that I'm initializing the variable in all the cases and stated: "Variable 'x' might not have been initialized". I do not want to put a default case.
Code example:
public enum eTest {
One,
Two
}
public class Test {
public void method(eTest value) {
String toPrint;
switch (value) {
case One:
toPrint = "One";
break;
case Two:
toPrint = "Two";
break;
}
System.out.println(toPrint); // <-- said error
}
}
I do not want to initialize the variable but I'm not sure there is a way to do this without initializing (I'd love to learn I'm wrong). Assuming this is not possible I wanted to make sure that new enum values will have to be added to this switch.
First try:
I've tried adding the "Enum 'switch' statement that misses case" to the Android Studio settings, but that has two issues:
It does not fail the build (only shows the place with a red marker).
It depends on the local configuration, and I'd like something that can be enforced on all users.
Second try:
I found that this should be possible with lintOptions in the build.gradle file (I'm using Android Studio, as mentioned), however I could not make it work as desired. I've added the following options to the build.gradle:
lintOptions {
enable 'EnumSwitchStatementWhichMissesCases'
abortOnError true
}
This did not work as well, I'm assuming because of two possible issues:
The name is wrong (I took it from the xml that Android Studio created when using the settings).
The default severity of this issue is warning and not error, however I could not find how to change the severity of an issue.
Third try:
It should be possible to add a lint.xml to the Android Studio project, I tried this as well but it did not fail the build, so I'm assuming I did something wrong there. I put the following in the AndroidManifest location:
<?xml version="1.0" encoding="UTF-8"?>
<lint>
<issue id="EnumSwitchStatementWhichMissesCases" severity="error" />
</lint>
Furthermore:
I've seen this answer, but this is not what I'm looking for, and since this is about a specific build process, I hope that there's a better solution.
The question:
Is it possible to:
1. Solve the original problem. edit: this cannot be done (thanks Blackbelt - see comment below)
and if not:
2. Add the said option to the build process (any option that can be enforced on other users is welcome).
Edit: clarification - I would like to know how to prevent enums with missing cases in compile time, using lint in Android Studio
This error comes from the Java compiler, not from an IntelliJ IDEA inspection or the Android linter. You will see exactly the same error if you compile a regular Java class (non-Android) with the command-line Java compiler. Because of that, none of your attempts to fix it work. The EnumSwitchStatementWhichMissesCases inspection detects a different kind of problem which doesn't occur in this situation.
The reason why the Java compiler reports this as an error is because Java supports separate compilation of classes. Even if right now your switch covers all possible cases of the enum, it's possible that the enum class will be recompiled at a later time and will include additional entries, which will not be handled by your switch.
Because of that, you need to make sure that the variable is initialized even if an unknown enum entry is passed to the method. You can do so either by adding an initializer to the variable declaration or by adding a default branch to the switch (the code in the branch can simply throw an error).
Create a default case.
enum myEnum(one, two, error)
String toPrint;
switch (myEnum)
{
case(one):
toPrint = "one";
break;
case (two):
toPrint = "two";
break;
default:
toPrint = "error";
}

Proguard shrinks too much

Since ADT 17 you can find in the gen folder a BuildConfig class with a DEBUG constant. I often use this constant in my code, since ADT changes the value automatically when you export the application.
However with Proguard this doesn't work anymore. E.g. I have following snippet:
if (!BuildConfig.DEBUG) {
ACRA.init(this);
}
Proguard notices, that DEBUG is true, so it removes this snippet completely and shrinks the app. After that ADT changes DEBUG constant, but this is too late.
The only solution I know is to create my own DEBUG constant and to change it manually again. But I really like the functionality of ADT. Do you know a better solution?
Thanks in advance.
Edit:
There is a workaround. Create your own DEBUG constant, which is initialized at runtime:
debug = (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE));
I create this variable at the very first in the onCreate method of my Application class. That is a workaround, which works, but it isn't the solution of the problem.

better way to do Debug only assert code

I am writing my first Android application and I am liberally using asserts() from junit.framework.Assert
I would like to find a way to ensure that the asserts are only compiled into the debug build, not in the release build.
I know how to query the android:debuggable attribute from the manifest so I could create a variable and accomplish this in the following fashon:
static final boolean mDebug = ...
if (mDebug)
Assert.assertNotNull(view);
Is there a better way to do this? i.e. I would prefer not to use an if() with each assert.
thanks
I think the Java language's assert keyword is likely what you want. Under the covers, the assert keyword essentially compiles into Dalvik byte code that does two things:
Checks whether the static variable assertionsDisabled (set in the class' static constructor via a call to java.lang.Class.desiredAssertionStatus()) is != 0 and if so, does nothing
If it is 0, then it checks the assertion expression and throws a java.lang.AssertionError if the expression resolves to false, effectively terminating your application.
The Dalvik runtime by default has assertions turned off, and therefore desiredAssertionStatus always returns 1 (or more precisely, some non-zero value). This is akin to running in "retail" mode. In order to turn on "debug" mode, you can run the following command against the emulator or the device:
adb shell setprop debug.assert 1
and this should do the trick (should work on the emulator or any rooted debugging-ready device).
Note however that the aforementioned Dalvik code that checks the value of assertionsDisabled and throws an AssertionError if the expression is false is always included in your byte code and liberal sprinkling of asserts in your code may lead to byte code bloat.
Please see this for a bit more detail: Can I use assert on Android devices?
If you're concerned about shipping code with the JUnit asserts in (or any other class path), you can use the ProGuard config option 'assumenosideeffects', which will strip out a class path on the assumption that removing it does nothing to the code.
Eg.
-assumenosideeffects class junit.framework.Assert {
*;
}
I have a common debug library I put all my testing methods in, and then use this option to strip it from my released apps.
This also removes the hard to spot problem of strings being manipulated that are never used in release code. For example if you write a debug log method, and in that method you check for debug mode before logging the string, you are still constructing the string, allocating memory, calling the method, but then opting to do nothing. Stripping the class out then removes the calls entirely, meaning as long as your string is constructed inside the method call, it goes away as well.
Make sure it is genuinely safe to just strip the lines out however, as it is done with no checking on ProGuard's part. Removing any void returning method will be fine, however if you are taking any return values from whatever you are removing, make sure you aren't using them for actual operational logic.
I mean if you were using a language feature, like assert(), the compiler should be able to strip that out. But this is an actual class and if a class is referenced by executable code it will be included or assumed included in the final product by the compiler.
However there is nothing stopping you from creating a script that removes all the references to the Assert class in all of your code base before compilation.
Another approach would be to make a test project that targets your application and within JUnit tests actually calls the Assert on the areas which you want to make sure work. I personally like this approach because it is a nice and clean separation of test and application.
If you are just worried about the having an if-statement everywhere, then just wrap Assert with your own class, DebuggableAssert which does that check before each call to Assert.X. It will be sort of less performant because of the method entry/exit and the conditionals but if you can maintain your code better then it might be worth it.

Categories

Resources