Writing JUnit tests for Toasts in an Android app - java

I often use Toast.makeText().show() to display messages to the user of my Android app. These can be instructions what to do next or error messages. As part of my JUnit tests, I would like to include assertions that these messages appear when expected. How do I go about doing this?

I do it by using Robotium framework, and calling this immediately after the toast is shown:
TextView toastTextView = solo.getText(0);
if(toastTextView != null){
String toastText = toastTextView.getText().toString();
assertEquals(toastText, "Your expected text here");
}
//wait for Toast to close
solo.waitForDialogToClose(5000);

Since originally asking this question, I have found the following solution which works well for me:
public static void waitForToast(Solo solo, String message) {
Assert.assertTrue(solo.waitForDialogToOpen(TIME_OUT));
Assert.assertTrue(solo.searchText(message));
}

Related

AdMob shows real ads even when using a test unit id; Android

TLDR: I get real ads even if I use a sample unit id provided by Google for testing.
I implemented native ads in my application.
I am using the Native Advanced sample ad unit as described here:
https://developers.google.com/admob/android/test-ads
However, the ads I get look very real, even though they have a "Test Ad" text in the title, and they also redirect me to real company websites. This has not happened with banner ads, I only got Google sample ads previously (e.g. Nice job, this is a test ad).
Some of the ads are coming from well-known restaurants in my country, and clicking on them navigates me to their website. I don't use my own unit id anywhere.
This is the code I use to initialize ads.
public static final String UNIFIED_AD_UNIT_ID = "ca-app-pub-3940256099942544/2247696110";
MobileAds.initialize(context, initializationStatus -> {
});
AdLoader adLoader = new AdLoader.Builder(context, UNIFIED_AD_UNIT_ID)
.forUnifiedNativeAd(unifiedNativeAd -> {
populateNativeAdView(unifiedNativeAd, nativeAdView);
}).build();
adLoader.loadAd(new AdRequest.Builder().build());
}
Is this a bug, or am I doing something wrong? (Or are these really test ads?) I really don't want to get banned from AdMob.
If you start your App running Android Studio, you can get the test device id for your device from the logcat at the bottom of Android Studio. Add this to your builder. By the way, the ads you are getting are looking like they should.

How to click button inside method Adapter in RecyclerView?

I am working on stripe-terminal-android-app, to connect to BBPOS 2X Reader device,
wanted to click-item from list,(recyclerView).
I am trying to do:
when list of devices appears(readers), I am checking if readers.size()==1, then click first-device from list,else show recyclerView();
I have very less experience in Android(coming from JS, PY), :)
After going through debugger to understand flow of program-running, I used F8 key, or stepOver the functions one by one,
and where value is assigned to convert in displayble-format in adapter as here.
public ReaderAdapter(#NotNull DiscoveryViewModel viewModel) {
super();
this.viewModel = viewModel;
if (viewModel.readers.getValue() == null) {
readers = new ArrayList<>();
} else {
readers = viewModel.readers.getValue();
if(readers.size() == 1){
Log.e(TAG, "readers.size() is 1 "+ readers.size());
}
}
}
then in ReaderHolder-file, values are bind() as
void bind(#NotNull Reader reader) {
binding.setItem(reader);
binding.setHandler(clickListener);
binding.executePendingBindings();
}
}
I tried assigining button and manually clicking when only-one device appears, by clicing on reader[0], can't do that by findViewById inside Adapter file, to call onClick() method manually,
I tired another StackOverflow's answer but didn't understood, from here.
Main fragment is discovery-fragment,
how can I click first-device by checking readers.size()==1, then click onClick()?
my final-goal is to automate, whole stripe-terminal-payment process on android.
extra-info:
I am fetching data from python-odoo server, then using url, will open app through browser, (done this part), then device will be selected automatically as everytime-no any devices will be present except one,
so will automatically select that from recyclerView, then proceed.
I have asked for help in detailed way on GitHub-issues, and started learning Android's concepts for this app(by customizing stripe's demo app, which works great, but I wanted to avoid manually clicking/selection of devices).

Android studio - Reading whatsapp notifications problem

I'm developing an android app and part of it needs to read WhatsApp messages by the notifications and analyze them.
I'm using a NotificationListenerService and it is working, however, I'm having a problem that notifications are being "analyzed" twice when I get the notification and then get a Message from other chat.
What I want is to analyze each message (Notification) once.
I already tried to save the notification sortKey or the StatusBarNotification key in a HashSet and then check, if it already contains the key every time, however that does not work.
Here is the code that in onNotificationPosted function -
String pack = sbn.getPackageName();
if (pack.equals("com.whatsapp")) {
Bundle extras = sbn.getNotification().extras;
if (extras.getCharSequence("android.text") != null && extras.getString("android.title") != null) {
if (sbn.getNotification().getSortKey() != null) {
String title = extras.getString("android.title");
String text = extras.getCharSequence("android.text").toString();
//Checking if it's from specic group and analyzing the message and
//doing what needs to be done, not related to the problem.
}
}
}
The result I want is that every notification will be analyzed once and not get posted again if some other messages arrive in other chats
Without knowing the inner workings of WhatsApp, it's hard to tell what you should exactly do, because it appears they reuse Actions/Extras for various things (which makes sense anyway).
In this case though, you could keep a list/map of the ones you've already "analyzed" and if you get it again, discard it.

Why do app gets stopped unexpectedly everytime using any code

My apologies
Hi, I am a newbie to the advance level programming. I have been working around with the basics and the syntax of the language.
I have searched enough
The problem I am having is, that each time, I write the code to handle the events in my App, it gets stopped. I have tried following step by step coding of the video from Treehouse tutorial of using the onClick and I have tried to follow the Android's official developer documents too. I have also looked into the codes at some sites (including and specially Stack Overflow).
All in vain
But each time I run the code, app works and when it has to execute the methods and functions, it gives me an alert saying App (Number Converter) stopped Unexpectedly. I am creating an app to convert the numbers from and to the 4 number systems, decimal, binary, octal and hexadecimal.
But, I am not able to get to the point why and why every time I write the code that is same, doesn't work and app stops.
Here is the code I am trying:
Button frmDeciToOct = (Button) findViewById(R.id.fromDecToOct);
/* here is the method that is the onClick */
frmDeciToBin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
/* getting the edit text view */
EditText edtTxt = (EditText) findViewById(R.id.decimalValue);
/* to string... */
String value = edtTxt.getText().toString();
/* conversion to int, I saw this method on SO's answer */
int value2 = Integer.valueOf(value);
/* createBinOfDeci is a method, I will post its code after this */
String result = createBinOfDeci(value2);
/* get the text view */
TextView txtView = (TextView) findViewById(R.id.fromDeciRes);
/* set the text as a result */
txtView.setText(result);
}
});
Here is the code for my method createBinOfDeci():
public String createBinOfDeci (int deci) {
String result = "";
result = Integer.toBinaryString(deci);
return result;
}
The only thing that I am getting is that, I am using Windows and it gets crashed due to less RAM amount here! I am truly out of guesses and answers. Any help would be appreciated.
As #CommonsWare suggested, to check the LogCat, and I saw that it showed me a few errors.
Which was a clear sign of saying: The values are not correctly matching up.
Then I came up to the point, that the values weren't actually filled. They were empty, and I was running the code on a null hehe.
I just added the value and it worked!
Thanks guys (for the LogCat suggestion).

Why doesn't "System.out.println" work in Android?

I want to print something in console, so that I can debug it. But for some reason, nothing prints in my Android application.
How do I debug then?
public class HelloWebview extends Activity {
WebView webview;
private static final String LOG_TAG = "WebViewDemo";
private class HelloWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
webview = (WebView) findViewById(R.id.webview);
webview.setWebViewClient(new HelloWebViewClient());
webview.getSettings().setJavaScriptEnabled(true);
webview.setWebChromeClient(new MyWebChromeClient());
webview.loadUrl("http://example.com/");
System.out.println("I am here");
}
Correction:
On the emulator and most devices System.out.println gets redirected to LogCat and printed using Log.i(). This may not be true on very old or custom Android versions.
Original:
There is no console to send the messages to so the System.out.println messages get lost. In the same way this happens when you run a "traditional" Java application with javaw.
Instead, you can use the Android Log class:
Log.d("MyApp","I am here");
You can then view the log either in the Logcat view in Eclipse, or by running the following command:
adb logcat
It's good to get in to the habit of looking at logcat output as that is also where the Stack Traces of any uncaught Exceptions are displayed.
The first Entry to every logging call is the log tag which identifies the source of the log message. This is helpful as you can filter the output of the log to show just your messages. To make sure that you're consistent with your log tag it's probably best to define it once as a static final String somewhere.
Log.d(MyActivity.LOG_TAG,"Application started");
There are five one-letter methods in Log corresponding to the following levels:
e() - Error
w() - Warning
i() - Information
d() - Debug
v() - Verbose
wtf() - What a Terrible Failure
The documentation says the following about the levels:
Verbose should never be compiled into an application except during development. Debug logs are compiled in but stripped at runtime. Error, warning and info logs are always kept.
Use the Log class. Output visible with LogCat
Yes it does. If you're using the emulator, it will show in the Logcat view under the System.out tag. Write something and try it in your emulator.
Of course, to see the result in logcat, you should set the Log level at least to "Info" (Log level in logcat); otherwise, as it happened to me, you won't see your output.
if you really need System.out.println to work(eg. it's called from third party library). you can simply use reflection to change out field in System.class:
try{
Field outField = System.class.getDeclaredField("out");
Field modifiersField = Field.class.getDeclaredField("accessFlags");
modifiersField.setAccessible(true);
modifiersField.set(outField, outField.getModifiers() & ~Modifier.FINAL);
outField.setAccessible(true);
outField.set(null, new PrintStream(new RedirectLogOutputStream());
}catch(NoSuchFieldException e){
e.printStackTrace();
}catch(IllegalAccessException e){
e.printStackTrace();
}
RedirectLogOutputStream class:
public class RedirectLogOutputStream extends OutputStream{
private String mCache;
#Override
public void write(int b) throws IOException{
if(mCache == null) mCache = "";
if(((char) b) == '\n'){
Log.i("redirect from system.out", mCache);
mCache = "";
}else{
mCache += (char) b;
}
}
}
it is not displayed in your application... it is under your emulator's logcat
System.out.println("...") is displayed on the Android Monitor in Android Studio
There is no place on your phone that you can read the System.out.println();
Instead, if you want to see the result of something either look at your logcat/console window or make a Toast or a Snackbar (if you're on a newer device) appear on the device's screen with the message :)
That's what i do when i have to check for example where it goes in a switch case code! Have fun coding! :)
I'll leave this for further visitors as for me it was something about the main thread being unable to System.out.println.
public class LogUtil {
private static String log = "";
private static boolean started = false;
public static void print(String s) {
//Start the thread unless it's already running
if(!started) {
start();
}
//Append a String to the log
log += s;
}
public static void println(String s) {
//Start the thread unless it's already running
if(!started) {
start();
}
//Append a String to the log with a newline.
//NOTE: Change to print(s + "\n") if you don't want it to trim the last newline.
log += (s.endsWith("\n") )? s : (s + "\n");
}
private static void start() {
//Creates a new Thread responsible for showing the logs.
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
while(true) {
//Execute 100 times per second to save CPU cycles.
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//If the log variable has any contents...
if(!log.isEmpty()) {
//...print it and clear the log variable for new data.
System.out.print(log);
log = "";
}
}
}
});
thread.start();
started = true;
}
}
Usage: LogUtil.println("This is a string");
I dont having fancy IDE to use LogCat as I use a mobile IDE.
I had to use various other methods and I have the classes and utilties for you to use if you need.
class jav.android.Msg. Has a collection of static methods.
A: methods for printing android TOASTS.
B: methods for popping up a dialog box.
Each method requires a valid Context. You can set the default context.
A more ambitious way, An Android Console. You instantiate a handle to the console in your app, which fires up the console(if it is installed), and you can write to the console. I recently updated the console to implement reading input from the console. Which doesnt return until the input is recieved, like a regular console.
A: Download and install Android Console( get it from me)
B: A java file is shipped with it(jav.android.console.IConsole). Place it at the appropriate directory. It contains the methods to operate Android Console.
C: Call the constructor which completes the initialization.
D: read<*> and write the console.
There is still work to do. Namely, since OnServiceConnected is not called immediately, You cannot use IConsole in the same function you instantiated it.
Before creating Android Console, I created Console Dialog, which was a dialog operating in the same app to resemble a console. Pro: no need to wait on OnServiceConnected to use it. Con: When app crashes, you dont get the message that crashed the app.
Since Android Console is a seperate app in a seperate process, if your app crashes, you definately get to see the error. Furthermore IConsole sets an uncaught exception handler in your app incase you are not keen in exception handling. It pretty much prints the stack traces and exception messages to Android Console. Finally, if Android Console crashes, it sends its stacktrace and exceptions to you and you can choose an app to read it. Actually, AndroidConsole is not required to crash.
Edit Extras
I noticed that my while APK Builder has no LogCat; AIDE does. Then I realized a pro of using my Android Console anyhow.
Android Console is design to take up only a portion of the screen, so you can see both your app, and data emitted from your app to the console. This is not possible with AIDE. So I I want to touch the screen and see coordinates, Android Console makes this easy.
Android Console is designed to pop up when you write to it.
Android Console will hide when you backpress.
Solution that worked for me:
Under Logcat. (To show Logcat if not already shown. Click View menu-->Tool Windows-->Logcat). It is shown as System.out not as System.out.println as you might expect it. Rebuild the app if you have not already.
In the picture, highlighted yellow shows the System.out and output "Hello again".
Recently I noticed the same issue in Android Studio 3.3. I closed the other Android studio projects and Logcat started working. The accepted answer above is not logical at all.

Categories

Resources