I installed Android Studio yesterday, and I tried to use the LogCat to see the logs. But there is nothing to show in the logcat. I used the terminal to run ./adb logcat and it works.
Is there someone who can explain to me how to use logcat in Android Studio?
Restarting logcat helps me always.
I get into this state often. Logcat is blank. Debugging works, I can hit breakpoints. No filters are set. Log level is on Verbose. I fix it by repeatedly looping through the following:
Restart logcat (see Zatziky's answer above)
Change the log level to Debug (or anything else) and back to Verbose.
unplugging and plugging back in the device
running adb kill-server && adb start-server
Close Android Studio and launch ddms on the command line.
Restart Android Studio
And finally restarting the computer if all else fails.
The problem is intermittent, I think Android Studio is just buggy.
I had the same problem but I solved by the following steps, Try this once.
1) In the android studio.
2) Open android Monitor window(bottom of android studio)
3) You can see the drop down in the right corner(spinner)
4) select -- Show only Selected application.
You need to press Alt+6 twice to restart the logcat window. That way it'll show the log outputs.
The problem mainly happens in debug mode.
Best way to fix some unnecessary changes is to invalidate caches
Go to FILE -> click "INVALIDATE CACHES/RESTART" then a dialog box will pop-up,
Select "INVALIDATE CACHES/RESTART" button.
Android studio will automatically restart and rebuild the index.
These helped me :
1.Enable ADB integration
2. Go to Android Device Monitor
Check if your device is online and Create a required filter
Run this command in terminal. It will start working again.
adb kill-server && adb start-server
Restarting Android Studio helped me.
In android Studio application you need to click Debug application option (Shift+f9) to run in debug mode and to enable LogCat.
Not a technical answer but you might want to check the search box for the logcat. If there is any character inputted, your logcat will be empty as it will be searching for that certain character or word, and then if its not present, your logcat log will be totally empty.
Make sure you have Logger buffer sizes propper value in your emulator developer menu option.
For me, the issue was that I had two emulators with the same name (I created it, deleted it, and then created it again with the same name). There were two emulator entries in the logcat dropdown and it was connected to the wrong one. All I had to do was switch to the other one. I prevented the problem permanently by renaming the emulator.
**
Read this if you are still stuck with logcat being empty
**
I've just solved this after MONTHS of annoyment and trouble.
Nothing helped, the device monitor worked fine during debugging but the standard logcat view was always empty.
The reason was annoyingly simple:
The logcat view was there but it had been moved to 0 width by an update!
You are in "ALT 6" Tab, you see two tabs in there "ADB logs" and "Devices | logcat"
Devices | logcat really means that it consists of Devices AND logcat, split by a vertical border.
The vertical border can be moved and during an update it seems to have moved to 100% right.
This results in the logcat to be collected but not displayed, move your mouse pointer to the right of the tool window and just DRAG logcat back into view.
This solution won't help everyone but I found many people with working ADB connection and still no logcat output, those might be hit by the same problem.
Try to close the project and re-open it .It worked for me. Logs will be reappear.
In my case, I removed "image" from the little dropdown on the right. It showed up just fine after that. That's because it will be searching the log for the keyword in that searchbox, so if it doesn't find any matches, it returns blank
It's weird to still encounter this problem even on a recent version of Android Studio. I read through the long list of solutions but they did not work for me.
The accepted answer worked on an earlier version of Android Studio ( I guess it was v2.3)
I did the following to get Logcat working again:
Logcat > Show only selected application > No filters
Logcat > No filters > Show only selected application
I expected resetting logcat should ideally give me the same effect but it didn't. Manually toggling filter was the only thing that worked.
This is on Android Studio 3.0.1 (stable) (I can't update it before finishing the current project)
The issue occurred when I started Android studio in the morning to continue the work I left at night. I hope the devs will look into this. It was painstaking to try over 15 solutions from stackoverflow and still see no result. It's even irritating to reveal another solution for future victims of this issue.
When everything else didn't work, here's what I did. Since adb logcat worked nicely, I decided to rely on it. Running adb logcat -v color in the Android Studio's embedded terminal produced outputs similar to the normal logcat, and allowed code links to work too:
But this came with a few issues:
You can't specify a package to watch. Using the --pid=<your PID> option, you can watch the output of a single process. But since every time you restart your app the PID changes, you have re-run this command with every restart.
The colors are annoying (in my opinion).
The output fields are not aligned with previous messages, the whole thing is not well formatted which makes following the logcat much harder than it should be (the same happens with the embedded logcat, though).
So I decided to make my own tool to automatically watch my package PID(s) and prettify the logcat output:
import java.awt.AWTException;
import java.io.*;
import java.util.ArrayList;
import java.awt.Robot;
import java.awt.event.KeyEvent;
public class Logcat {
private static final String ADB_FILE_PATH = "adb";
// Customizations,
private static final Color V_COLOR = Color.RESET;
private static final Color D_COLOR = Color.RESET;
private static final Color I_COLOR = Color.RESET;
private static final Color W_COLOR = Color.BLUE;
private static final Color E_COLOR = Color.RED_BRIGHT;
private static final Color HINT_COLOR = Color.MAGENTA_BOLD_BRIGHT;
private static final Color OTHER_COLOR = Color.GREEN_BOLD_BRIGHT;
private static final int DATE_LENGTH = 5;
private static final int TIME_LENGTH = 12;
private static final int PROCESS_ID_LENGTH = 5;
private static final int THREAD_ID_LENGTH = 5;
private static final int LOG_LEVEL_LENGTH = 1;
private static final int TAG_LENGTH = 20;
private static final int MESSAGE_LENGTH = 110;
private static final String SEPARATOR = " | ";
private static final String CONTINUATION = "→";
private static final String INDENTATION = " ";
private static final int PROCESS_IDS_UPDATE_INTERVAL_MILLIS = 1224;
private static final int HISTORY_LENGTH = 1000;
// State,
private static boolean skipProcessIDCheck;
private static ArrayList<String> processIDs = new ArrayList<String>();
private static String logLevelToShow="V"; // All.
private static Process logcatProcess;
private static boolean appClosed;
private static boolean stopEverything;
private static String[] history = new String[HISTORY_LENGTH];
private static int currentLocationInHistory, historyLength;
public static void main(final String args[]) {
clearAndroidStudioConsole();
System.out.println("besm Allah");
// Get processes ids of the provided package,
if (args.length==0) {
skipProcessIDCheck = true;
} else {
skipProcessIDCheck = false;
getProcessIDs (args[0]); // Do it once before we start.
monitorProcessIDs(args[0]); // Do it periodically from now on.
}
// Start capturing and prettifying logcat,
if (!monitorLogcat()) {
stopEverything = true;
return;
}
// Handle user input,
handleUserInput();
}
private static void watch(final Process process, final ProcessListener listener) {
// Read process standard output and send it to the listener line by line,
new Thread() {
public void run() {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = "";
try {
do {
if (bufferedReader.ready()) {
line = bufferedReader.readLine();
if (line!=null && !line.isEmpty()) listener.onNewLine(line);
} else {
Thread.sleep(100);
}
} while (line!=null && !stopEverything);
} catch (Exception e) { e.printStackTrace(); }
}
}.start();
}
private static void monitorProcessIDs(String packageName) {
// Continuously monitor the process IDs of this package and update when changed,
new Thread() {
public void run() {
do {
try { Thread.sleep(PROCESS_IDS_UPDATE_INTERVAL_MILLIS); } catch (InterruptedException e) {}
getProcessIDs(packageName);
} while (!stopEverything);
}
}.start();
}
private static void getProcessIDs(String packageName) {
// Get the process IDs associated with this package once,
ArrayList<String> newProcessIDs = new ArrayList<String>();
Runtime runtime = Runtime.getRuntime();
try {
Process getPIDProcess = runtime.exec(ADB_FILE_PATH + " shell ps");
watch(getPIDProcess, (line) -> {
if (line.contains(packageName)) {
newProcessIDs.add(removeRedundantSpaces(line).split(" ")[1]);
}
});
getPIDProcess.waitFor();
Thread.sleep(500); // Make sure we've already handled all the input from the process.
} catch (Exception e) { e.printStackTrace(); }
// Return immediately if program is closed,
if (stopEverything) return ;
// Some action upon getting the pid(s),
boolean shouldRepeatHistory = false;
if (newProcessIDs.isEmpty()) {
// Just closed,
if (!appClosed) {
appClosed = true;
prettify("----- App closed -----");
}
} else if (appClosed) {
// Just opened, clear,
appClosed = false;
clearAndroidStudioConsole();
prettify("----- App opened -----");
shouldRepeatHistory = true;
} else {
// Detect changes in processes,
for (String pid : newProcessIDs) {
if (!processIDs.contains(pid)) {
clearAndroidStudioConsole();
prettify("----- Process(es) changed (or app restarted - some logs could have been missed) -----");
shouldRepeatHistory = true;
break ;
}
}
}
// Set the new PID(s),
processIDs = newProcessIDs;
if (shouldRepeatHistory) repeatHistory();
}
private static boolean monitorLogcat() {
Runtime runtime = Runtime.getRuntime();
try {
logcatProcess = runtime.exec(ADB_FILE_PATH + " logcat -v threadtime");
watch(logcatProcess, (line) -> {
// Learn history, in case we need to repeat it,
if (appClosed || processLogcatLine(line)) {
history[currentLocationInHistory] = line;
currentLocationInHistory = (currentLocationInHistory + 1) % history.length;
if (historyLength<history.length) historyLength++;
}
});
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
private static boolean processLogcatLine(String line) {
try {
return prettify(line);
} catch (Exception e) {
print(line, OTHER_COLOR);
System.out.println();
// Debug,
e.printStackTrace();
return true;
}
}
// Returns true if line should be kept in history,
private static synchronized boolean prettify(String line) {
if (line.startsWith("-")) {
// It's a "beginning of <something>" line,
print(line, HINT_COLOR);
System.out.println();
return true;
}
// Get the individual fields,
String date = line.substring(0, line.indexOf(' ')); line = line.substring(line.indexOf(' ')+1); line = line.trim();
String time = line.substring(0, line.indexOf(' ')); line = line.substring(line.indexOf(' ')+1); line = line.trim();
String processID = line.substring(0, line.indexOf(' ')); line = line.substring(line.indexOf(' ')+1); line = line.trim();
// Break early if possible,
if (!skipProcessIDCheck && !processIDs.contains(processID.trim())) return false;
// Continue parsing,
String threadID = line.substring(0, line.indexOf(' ')); line = line.substring(line.indexOf(' ')+1); line = line.trim();
String logLevel = line.substring(0, line.indexOf(' ')); line = line.substring(line.indexOf(' ')+1); line = line.trim();
// Break early if possible,
switch (logLevel) {
case "V": if (!"V" .contains(logLevelToShow)) return true; break;
case "D": if (!"VD" .contains(logLevelToShow)) return true; break;
case "I": if (!"VDI" .contains(logLevelToShow)) return true; break;
case "W": if (!"VDIW" .contains(logLevelToShow)) return true; break;
case "E": if (!"VDIWE".contains(logLevelToShow)) return true; break;
}
// Continue parsing,
String tag = line.substring(0, line.indexOf(':')); line = line.substring(line.indexOf(':')+1); line = line.trim();
// Because some tags have a trailing ":",
if (line.startsWith(":")) {
tag += ":";
line = line.substring(1);
}
// Indent lines starting by "at",
String indentation = "";
if (line.startsWith("at ")) {
indentation = " " + INDENTATION;
line = " " + INDENTATION + line;
}
// Print the prettified log,
Color color;
switch (logLevel) {
case "V": color = V_COLOR; break;
case "D": color = D_COLOR; break;
case "I": color = I_COLOR; break;
case "W": color = W_COLOR; break;
case "E": color = E_COLOR; break;
default:
color = Color.RESET;
}
String fields = adjustLength( date, DATE_LENGTH) + SEPARATOR +
adjustLength( time, TIME_LENGTH) + SEPARATOR +
adjustLength(processID, PROCESS_ID_LENGTH) + SEPARATOR +
adjustLength( threadID, THREAD_ID_LENGTH) + SEPARATOR +
adjustLength( logLevel, LOG_LEVEL_LENGTH) + SEPARATOR +
adjustLength( tag, TAG_LENGTH) + SEPARATOR;
// Split the message onto multiple lines if needed,
String message = chunkPreservingParentheses(line, MESSAGE_LENGTH, 2);
print(fields + message, color);
System.out.println();
while (line.length() > message.length()) {
// Debug,
//print(line, OTHER_COLOR);
//System.out.println("Line: " + line.length() + "length: " + message.length() + ", cont: " + CONTINUATION.length() + "dent: " + indentation.length());
//System.out.println();
// Remove the already printed part.
line = line.substring(message.length()-CONTINUATION.length());
// Add a dot to make links work,
boolean shouldAddDot=false;
if (line.matches("^[^\\.]*\\(.*:[123456789][1234567890]*\\).*")) shouldAddDot = true;
// Indent,
line = (shouldAddDot ? "." : (indentation.isEmpty() ? "" : " ")) + indentation + line;
// Take another chunk,
message = chunkPreservingParentheses(line, MESSAGE_LENGTH, 2+indentation.length());
// Front pad to align this part with the message body,
String paddedMessage = message;
for (int i=0; i<fields.length(); i++) paddedMessage = ' ' + paddedMessage;
// Print,
print(paddedMessage, color);
System.out.println();
}
return true; // Keep in local buffer.
}
private static String adjustLength(String text, int length) {
while (text.length() < length) text += ' ';
if (text.length() > length) {
text = text.substring(0, length-CONTINUATION.length());
text += CONTINUATION;
}
return text;
}
private static String chunkPreservingParentheses(String text, int length, int minChunckLength) {
if (text.length() <= length) return text;
// Take a chunk out of the text,
String chunk = text.substring(0, length-CONTINUATION.length()) + CONTINUATION;
// Check if a paranthesis was opened and not closed,
int lastOpenParanthesisIndex = chunk.lastIndexOf('(');
int lastCloseParanthesisIndex = chunk.lastIndexOf(')');
if (lastCloseParanthesisIndex <= lastOpenParanthesisIndex) { // Also works when either is not found.
if (minChunckLength<1) minChunckLength = 1;
if (lastOpenParanthesisIndex > minChunckLength+CONTINUATION.length()) { // Avoid endless loops.
int includeParenthesisSize = (CONTINUATION.length()>0) ? 1 : 0;
chunk = text.substring(0, lastOpenParanthesisIndex+includeParenthesisSize-CONTINUATION.length()) + CONTINUATION;
}
}
return chunk;
}
private static void repeatHistory() {
int index = currentLocationInHistory-historyLength;
if (index < 0) index += history.length;
for (int i=0; i<historyLength; i++) {
processLogcatLine(history[index]);
index = (index + 1) % history.length;
}
}
private static void print(String text, Color color) {
System.out.print(color);
System.out.print(text);
System.out.print(Color.RESET);
}
private static String removeRedundantSpaces(String text) {
String newText = text.replace(" ", " ");
while (!text.equals(newText)) {
text = newText;
newText = text.replace(" ", " ");
}
return text;
}
private static void clearAndroidStudioConsole() {
// Couldn't find a reliable way to clear Intellij terminal scrollback, so we just print
// a LOT of newlines,
StringBuilder bunchOfNewLines = new StringBuilder();
for (int i=0; i<124; i++) bunchOfNewLines.append(System.lineSeparator());
System.out.print(bunchOfNewLines);
// Scroll the current line to the top of the window,
try {
// If we are on Windows,
new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();
} catch (Exception e) {
// We are not on Windows,
bunchOfNewLines = new StringBuilder();
for (int i=0; i<124; i++) bunchOfNewLines.append("\b\r");
System.out.print(bunchOfNewLines);
}
}
private static void handleUserInput() {
// Line read. Unfortunately, java doesn't provide character by character reading out of the box.
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String input = "";
do {
try {
if (bufferedReader.ready()) {
input = input = bufferedReader.readLine().toUpperCase();
// Set log level,
if (input.equals("V")||input.equals("D")||input.equals("I")||input.equals("W")||input.equals("E")) {
if (!logLevelToShow.equals(input)) {
logLevelToShow = input;
clearAndroidStudioConsole();
repeatHistory();
}
prettify("----- Log level set to " + logLevelToShow + " -----");
} else if (input.equals("C")) {
// Clear screen and history,
clearAndroidStudioConsole();
historyLength = 0;
}
} else {
Thread.sleep(100);
}
} catch (Exception e) { e.printStackTrace(); }
// Check if the logcat process is still alive,
if (!logcatProcess.isAlive()) {
prettify("----- adb logcat process terminated -----");
stopEverything = true;
}
} while (!stopEverything && !input.equals("Q"));
// Allow all monitoring threads to exit,
stopEverything = true;
}
interface ProcessListener {
void onNewLine(String line);
}
enum Color {
// Thanks to this answer: https://stackoverflow.com/a/51944613/1942069
//Color end string, color reset
RESET("\033[0m"),
// Regular Colors. Normal color, no bold, background color etc.
BLACK ("\033[0;30m"),
RED ("\033[0;31m"),
GREEN ("\033[0;32m"),
YELLOW ("\033[0;33m"),
BLUE ("\033[0;34m"),
MAGENTA("\033[0;35m"),
CYAN ("\033[0;36m"),
WHITE ("\033[0;37m"),
// Bold
BLACK_BOLD ("\033[1;30m"),
RED_BOLD ("\033[1;31m"),
GREEN_BOLD ("\033[1;32m"),
YELLOW_BOLD ("\033[1;33m"),
BLUE_BOLD ("\033[1;34m"),
MAGENTA_BOLD("\033[1;35m"),
CYAN_BOLD ("\033[1;36m"),
WHITE_BOLD ("\033[1;37m"),
// Underline
BLACK_UNDERLINED ("\033[4;30m"),
RED_UNDERLINED ("\033[4;31m"),
GREEN_UNDERLINED ("\033[4;32m"),
YELLOW_UNDERLINED ("\033[4;33m"),
BLUE_UNDERLINED ("\033[4;34m"),
MAGENTA_UNDERLINED("\033[4;35m"),
CYAN_UNDERLINED ("\033[4;36m"),
WHITE_UNDERLINED ("\033[4;37m"),
// Background
BLACK_BACKGROUND ("\033[40m"),
RED_BACKGROUND ("\033[41m"),
GREEN_BACKGROUND ("\033[42m"),
YELLOW_BACKGROUND ("\033[43m"),
BLUE_BACKGROUND ("\033[44m"),
MAGENTA_BACKGROUND("\033[45m"),
CYAN_BACKGROUND ("\033[46m"),
WHITE_BACKGROUND ("\033[47m"),
// High Intensity
BLACK_BRIGHT ("\033[0;90m"),
RED_BRIGHT ("\033[0;91m"),
GREEN_BRIGHT ("\033[0;92m"),
YELLOW_BRIGHT ("\033[0;93m"),
BLUE_BRIGHT ("\033[0;94m"),
MAGENTA_BRIGHT("\033[0;95m"),
CYAN_BRIGHT ("\033[0;96m"),
WHITE_BRIGHT ("\033[0;97m"),
// Bold High Intensity
BLACK_BOLD_BRIGHT ("\033[1;90m"),
RED_BOLD_BRIGHT ("\033[1;91m"),
GREEN_BOLD_BRIGHT ("\033[1;92m"),
YELLOW_BOLD_BRIGHT ("\033[1;93m"),
BLUE_BOLD_BRIGHT ("\033[1;94m"),
MAGENTA_BOLD_BRIGHT("\033[1;95m"),
CYAN_BOLD_BRIGHT ("\033[1;96m"),
WHITE_BOLD_BRIGHT ("\033[1;97m"),
// High Intensity backgrounds
BLACK_BACKGROUND_BRIGHT ("\033[0;100m"),
RED_BACKGROUND_BRIGHT ("\033[0;101m"),
GREEN_BACKGROUND_BRIGHT ("\033[0;102m"),
YELLOW_BACKGROUND_BRIGHT ("\033[0;103m"),
BLUE_BACKGROUND_BRIGHT ("\033[0;104m"),
MAGENTA_BACKGROUND_BRIGHT("\033[0;105m"),
CYAN_BACKGROUND_BRIGHT ("\033[0;106m"),
WHITE_BACKGROUND_BRIGHT ("\033[0;107m");
private final String code;
Color(String code) { this.code = code; }
#Override public String toString() { return code; }
}
}
Just dump this code into Logcat.java and compile using:
javac Logcat.java
And run inside the Android Studio's embedded terminal:
java Logcat <your.package.name>
For example:
java Logcat com.nomone.vr_desktop
The result looks like this:
It's highly customizable, I've separated most of the options in the first section of the app, so you can tweak the colors and formatting easily. If the adb tool is not in your PATH environment variable, just set its full path in the ADB_FILE_PATH variable (in the code) before compiling.
When the application is running, you can type the following shortcuts:
c to clear the screen and local buffer.
v, i, d, w, e to change the logcat level.
q to quit gracefully. Ctrl+c works too.
Unfortunately, you have to press enter after pressing these keys. Seems like Java doesn't allow single character input from console without writing system specific code. Sorry!
Disclaimer
This doesn't work if multiple devices are connected using adb.
I haven't thoroughly tested this. I've only used it for a while on a few devices.
I haven't tested this on Windows or Mac, but I tried to avoid using anything system specific, so it should still work.
I hope this solves your problem :)
In my case, in the developer options menu there is an option called
Revoke USB debugging authorisations.
Once you revoke all the existing authorisations it will ask again to trust the computer that you are using after that it started to show the logs again.
In Android 3.6.1 I had to:
Upgrade to latest Android Studio version (4.x.x)
Restart Logcat
Restart the app
Restart Android Studio
Restart the Android testing device
This may not be your issue, but I've found that when having multiple windows of Android Studio open, logcat is only directed to one of them, and not necessarily the one that's running an active application.
For example, Window 1 is where I'm developing a Tic-Tac-Toe app, and Window 2 is where I'm developing a weather app. If I run the weather app in debug mode, it's possible only Window 1 will be able to display logcat entries.
On the right side of tab "Devices logcat" there is the button "Show only Logcat from selected Process". Its not perfect, because everytime I run another process I need to push it again, but thats the only solution that works for me. So far...
For me, the problem was that the device was connected in the Charge only mode.
Changing the mode to Media device (MTP) (or Transfer files in some devices) solved the problem.
Step 1: Connect Your Phone with Android Developer option On and USB Debug On.
Step 2: Go TO View > Tools Window > Logcat
Step 3: Before Run Project Make Sure Your Phone Connect Android Studio. Then run application
Note: If You Can not Show Logcat Just Restart Android Studio : File > Invalid Caches/ restart
In Android studio 0.8.0 you should enable ADB integration through Tools -> Android, before run your app. Then the log cat will work correctly. Notice that if you make ADB integration disabled while your app is running and again make it enable, then the log cat dosen't show anything unless you rebuild your project.
In my case I just had filtered the output so it appeared empty even after restarting Logcat etc.
My problem solved, after I add android:debuggable="true" under application in your AndroiManifest.xml (even the ide mark as a wrong syntax!????)
I checked the answer and only found my mistake accidentally while checking my logcat.
Make sure the box on the right says "Show only selected application". Mine was showing "Firebase", so it showed me messages from Firebase.
In Android Studio 0.8.9, I opened Android Device Monitor, selected my emulator from the Devices list and got the output in the LogCat tab.
After that, I went back to the main view of Android Studio and selected Restore Logcat view in the right of the Android DDMS tab and there it was!
If this doesn't work, you could see your logcat in the Android Device Monitor as I explained in the first sentence.
Make sure you have enabled the build variant to "debug" in the Build Variants context menu. (You can find this at the bottom left corner of the window). This option will be set to release mode, if you have signed the apk for the application previously. This causes the debug messages not to show in the log cat.
Had the same issue today.
Apparently I had eclipse running too and all the logcat output was redirected to eclipse. Since the logs can only be shown at once place, make sure you dont have multiple debuggers running.
Related
I’ve run into a performance obstacle and I’m uncertain of the cause, all of this is running under VS2022 & Net6.0. As this is my 1st time using this combination of a modal windows form, and progress bar, with the work running on a background thread and two Progress objects updating the UI, the progress bar, and a text label, I don’t know where to attack the problem. Prior to placing the workload on a background thread, everything was snappy, searching a thousand files with about 600 lines of text in each, in about a minute. Naturally, the windows form was frozen during this, which is why the workload was placed on a background thread.
After doing so, the workload will be 25-50% complete before the UI starts displaying the values from the Progress objects, and overall, the entire process now takes 10x as long to complete. Progress objects aren’t skipping over any values sent to them, the UI thread just seems slow in getting the information. Likewise, if I try to drag the modal form to a new spot on the desktop it’s unresponsive for 20—30 seconds before it finally moves. One more thing, I can step through the code on the background thread and see it calling the Progress updaters, but the UI thread is just very slow in responding to them.
I could use some suggestions on how to uncover the problem or if clearly evident, point out where the likely problem could be. Here are the essential controls and methods used.
public class SearchProgressForm : Form
{
private System.Windows.Forms.Button btnSearch = new Button();
private System.Windows.Forms.TextBox txtTextSearch = new TextBox();
private System.Windows.Forms.Label lblSearchFile = new Label();
private System.Windows.Forms.ProgressBar SearchProgressBar = new ProgressBar();
public event LogSearchEventHandler SearchSucceededEvent;
protected void OnSearchSucceeded(LogSearchEventArguments p_eventArguments)
{
LogSearchEventHandler handler = SearchSucceededEvent;
if (handler != null)
{
handler(this, p_eventArguments);
}
}
private void InitializeComponent()
{
this.btnSearch.Name = "btnSearch";
this.btnSearch.Text = "Search";
this.btnSearch.Click += new System.EventHandler(this.btnSearch_Click);
this.lblSearchFile.Text = "Searching File: ";
this.txtTextSearch.Text = "search string";
}
public SearchProgressForm() { }
private void btnSearch_Click(object sender, EventArgs e)
{
this.SearchByText(this.txtTextSearch.Text);
}
private void SearchByText(string p_searchParameter)
{
// Setup a progress report for thr ProgressBar
var _progressBarUpdate = new Progress<int>(value =>
{
this.SearchProgressBar.Value = value;
this.SearchProgressBar.Refresh();
});
var _progressFileNameUpdate = new Progress<string>(value =>
{
this.lblSearchFile.Text = "Searching File For : " + value;
this.lblSearchFile.Refresh();
});
// Start search on a backgroud thread and report progress as it occurs
Task.Run(async () => await this.SearchByStringAsync(p_searchParameter, _progressBarUpdate, _progressFileNameUpdate));
}
private async Task SearchByStringAsync(string p_searchParameter, IProgress<int> p_progressBar, IProgress<string> p_progressFileName)
{
await Task.Delay(1);
TextFileReader textFileReader = new TextFileReader();
LogSearchEventArguments logSearchEventArguments = null;
long _sessionloopCount = 0;
long _totalTextLinesCount = this.GetTotalSearchCount(p_searchParameter, SearchType.TextString);
// Get file names from SQL table
var _logFiles = DataOperations.LogFileSortableList(null);
foreach (var log in _logFiles)
{
// Format a file name to be read from the file system
string _fileName = log.Directory + "\\" + log.FileName;
p_progressFileName.Report(log.FileName);
// If we've raised an event for this file, then stop iterating over remaning text
if (logSearchEventArguments != null)
{
logSearchEventArguments = null;
break;
}
// Read in file contents from file system
List<string> _fileContents = textFileReader.ReadAndReturnStringList(_fileName);
long _fileTotalRecordCount = _fileContents.Count;
long _fileRecordCount = 0;
foreach (var _line in _fileContents)
{
if (_line.ToUpper().Contains(p_searchParameter.ToUpper()))
{
// Raise an event so search parameter and file name can be captured in another form
logSearchEventArguments =
new LogSearchEventArguments
(
"TextSearch", p_searchParameter, SearchType.TextString, true, log,
new DateTime(
Convert.ToInt32("20" + log.FileName.Substring(14, 2)),
Convert.ToInt32(log.FileName.Substring(16, 2)),
Convert.ToInt32(log.FileName.Substring(18, 2)))
);
// We found a match, so no further searching is needed in this log file,
// and it's been flagged in the DB, so raise the event to save search parameter and file name
// then break out of this loop to get the next file to search in.
this.OnSearchSucceeded(logSearchEventArguments);
break;
}
// These calcs are based on actual searches performed
_fileRecordCount++;
_sessionloopCount++;
p_progressBar.Report(Convert.ToInt32((_sessionloopCount * 100) / _totalTextLinesCount));
}
// Because we exit a search as soon as the 1st match is made, need to resynch all counts
// and update the progress bar accordingly
if (_fileRecordCount < _fileTotalRecordCount)
{
long _countDifference = _fileTotalRecordCount - _fileRecordCount;
// Add count difference to sessionLoopCount and update progress bar
_sessionloopCount += _countDifference;
p_progressBar.Report(Convert.ToInt32((_sessionloopCount * 100) / _totalTextLinesCount));
}
}
//Search is complete set Progress to 100% and report before exiting
p_progressBar.Report(100);
// Close the modal SearchForm and exit
this.Close();
}
}
I solved this problem but I'm still not certain of what caused it. I eliminated the method "private void SearchByText(string p_searchParameter)" and moved the code there into the btnSearch_Click event handler so I could call my background worker "SearchByStringAsync" directly from the button click event handler.
I also updated the EFCore NuGet Packages, which were version Net6.0 to version 6.0.4, because of single line of code in my Async background method, "var _logFiles = DataOperations.LogFileSortableList(null)".
That call returned a Sortable BindingList, using BindingList <T>. Between the NuGet updates and a minor change on a custom comparer method in my BindingList <T> class, the windows modal form now updates the ProgressBar and Label text as expected, and the form now responds immediately to user interaction.
I have two 3d buttons in my scene and when I gaze into any of the buttons it will invoke OnPointerEnter callback and saving the object the pointer gazed to.
Upon pressing Fire1 on the Gamepad I apply materials taken from Resources folder.
My problem started when I gazed into the second button, and pressing Fire1 button will awkwardly changed both buttons at the same time.
This is the script I attached to both of the buttons
using UnityEngine;
using UnityEngine.EventSystems;
using Vuforia;
using System.Collections;
public class TriggerMethods : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
Material _mat;
GameObject targetObject;
Renderer rend;
int i = 0;
// Update is called once per frame
void Update () {
if (Input.GetButtonDown("Fire1"))
TukarMat();
}
public void OnPointerEnter(PointerEventData eventData)
{
targetObject = ExecuteEvents.GetEventHandler<IPointerEnterHandler>(eventData.pointerEnter);
}
public void OnPointerExit(PointerEventData eventData)
{
targetObject = null;
}
public void TukarMat()
{
Debug.Log("Value i = " + i);
if (i == 0)
{
ApplyTexture(i);
i++;
}
else if (i == 1)
{
ApplyTexture(i);
i++;
}
else if (i == 2)
{
ApplyTexture(i);
i = 0;
}
}
void ApplyTexture(int i)
{
rend = targetObject.GetComponent<Renderer>();
rend.enabled = true;
switch (i)
{
case 0:
_mat = Resources.Load("Balut", typeof(Material)) as Material;
rend.sharedMaterial = _mat;
break;
case 1:
_mat = Resources.Load("Khasiat", typeof(Material)) as Material;
rend.sharedMaterial = _mat;
break;
case 2:
_mat = Resources.Load("Alma", typeof(Material)) as Material;
rend.sharedMaterial = _mat;
break;
default:
break;
}
}
I sensed some logic error and tried making another class to only manage object the pointer gazed to but I was getting more confused.
Hope getting some helps
Thank you
TukarMat() is beeing called on both buttons when you press Fire1. If targetObject is really becoming null this should give an error on first button since it's trying to get component from a null object. Else, it'll change both as you said. Make sure OnPointerExit is beeing called.
Also, it seems you are changing the shared material.
The documentation suggests:
Modifying sharedMaterial will change the appearance of all objects using this material, and change material settings that are stored in the project too.
It is not recommended to modify materials returned by sharedMaterial. If you want to modify the material of a renderer use material instead.
So, try changing the material property instead of sharedMaterial since it'll change the material for that object only.
Using Visual studio 2010 and MFC Doc/View Applications I want my SDI application to start up completely hidden, and after sometime or with receiving some message from tray icon it shows the mainframe, view and so on. I change the line m_pMainWnd->ShowWindow(SW_NORMAL); to m_pMainWnd->ShowWindow(SW_HIDE); in BOOL CMyApp::InitInstance() but the main frame just flickers after executing the application and then goes hiiden what should I do inorder to avoid this problem and keep the showing capability of main frame when ever I want.
Here is the solution for SDI/MDI app: The new MFC (with VC2010) overrides the m_nCmdShow value with a setting stored in the system registry. To change this behaviour, simply override the LoadWindowPlacement virtual function in the application class.
BOOL CAdVisuoApp::LoadWindowPlacement(CRect& rectNormalPosition, int& nFflags, int& nShowCmd)
{
BOOL b = CWinAppEx::LoadWindowPlacement(rectNormalPosition, nFflags, nShowCmd);
nShowCmd = SW_HIDE;
return b;
}
Normally if you have VC2005 or earlier the following will do:
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
m_nCmdShow = SW_HIDE;
// Dispatch commands specified on the command line. Will return FALSE if
// app was launched with /RegServer, /Register, /Unregserver or /Unregister.
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// The one and only window has been initialized, so show and update it
m_pMainWnd->ShowWindow( m_nCmdShow);
m_pMainWnd->UpdateWindow();
Note that m_nCmdShow should be set to SW_HIDE before ProcessShallCommand for the flicker not to occur.
It looks like there might be a bug in VC2010 though. Since I have done this before it intrigued me and tried a fresh VC2010 project but it was not working. I noticed the problem was deep in the following MFC function.
BOOL CFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,
CWnd* pParentWnd, CCreateContext* pContext)
{
// only do this once
ASSERT_VALID_IDR(nIDResource);
ASSERT(m_nIDHelp == 0 || m_nIDHelp == nIDResource);
m_nIDHelp = nIDResource; // ID for help context (+HID_BASE_RESOURCE)
CString strFullString;
if (strFullString.LoadString(nIDResource))
AfxExtractSubString(m_strTitle, strFullString, 0); // first sub-string
VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
// attempt to create the window
LPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource);
CString strTitle = m_strTitle;
if (!Create(lpszClass, strTitle, dwDefaultStyle, rectDefault,
pParentWnd, ATL_MAKEINTRESOURCE(nIDResource), 0L, pContext))
{
return FALSE; // will self destruct on failure normally
}
// save the default menu handle
ASSERT(m_hWnd != NULL);
m_hMenuDefault = m_dwMenuBarState == AFX_MBS_VISIBLE ? ::GetMenu(m_hWnd) : m_hMenu;
// load accelerator resource
LoadAccelTable(ATL_MAKEINTRESOURCE(nIDResource));
if (pContext == NULL) // send initial update
SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);
return TRUE;
}
m_nCmdShow is still SW_HIDE when this function executes but it changes to SW_SHOWNORMAL when if (!Create(lpszClass... line executes. I don't know why this happens in VC2010 project only, sounds like a bug to me.
My sample project was SDI.
This comes from a dialog based application but you should be able to convert it to a Doc/View app as well. You need to handle the OnWindowPosChanging event. The key line is the the one inside the if statement. This allows my application to start completely hidden from view.
void CIPViewerDlg::OnWindowPosChanging( WINDOWPOS FAR* lpWindowPosition )
{
if( !m_bVisible )
{
lpWindowPosition->flags &= ~SWP_SHOWWINDOW;
}
CDialog::OnWindowPosChanging( lpWindowPosition );
}
Make sure that you are correctly turning off the WS_VISIBLE bit in CMainFrame::PreCreateWindow(CREATESTRUCT& cs). Something like this should worK:
cs.style &= ~WS_VISIBLE;
We had simply been negating the bit instead of turning it off, and we got away with it in VS 6.0 because this function was called only once. It is called twice in newer versions of Visual Studio, so in the second call we were flipping it right back on again. :-O
I tried all for Visual Studio 2010 and finished up with:
class CMainFrame : public CFrameWndEx
{
// ...
// Attributes
public:
BOOL m_bForceHidden;
// ...
// Overrides
public:
virtual void ActivateFrame(int nCmdShow = -1);
//...
};
CMainFrame::CMainFrame() : m_bForceHidden(TRUE)
{
// ...
}
void CMainFrame::ActivateFrame(int nCmdShow)
{
if(m_bForceHidden)
{
nCmdShow = SW_HIDE;
m_bForceHidden = FALSE;
}
CFrameWndEx::ActivateFrame(nCmdShow);
}
Other tricks did not work for me.
Found solution at:
http://forums.codeguru.com/showthread.php?478882-RESOLVED-Can-a-Doc-view-be-hidden-at-startup
I found in VS2017 (using BCGControlBar Pro which is what MFC Feature Pack was based on) that you have to handle things in two places:
BOOL CMainFrame::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle, CWnd* pParentWnd, CCreateContext* pContext)
{
if (!__super::LoadFrame(nIDResource, dwDefaultStyle, pParentWnd, pContext))
{
return FALSE;
}
// undo what __super::LoadFrame() does where it will set it to SW_NORMAL if not SW_MAXIMIZED
AfxGetApp()->m_nCmdShow = SW_HIDE;
}
BOOL CTheApp::LoadWindowPlacement(CRect& rectNormalPosition, int& nFflags, int& nShowCmd)
{
BOOL b = __super::LoadWindowPlacement(rectNormalPosition, nFflags, nShowCmd);
nShowCmd = SW_HIDE;
return b;
}
Using C# 4 in a Windows console application that continually reports progress how can I make the "redraw" of the screen more fluid?
I'd like to do one of the following:
- Have it only "redraw" the part of the screen that's changing (the progress portion) and leave the rest as is.
- "Redraw" the whole screen but not have it flicker.
Currently I re-write all the text (application name, etc.). Like this:
Console.Clear();
WriteTitle();
Console.WriteLine();
Console.WriteLine("Deleting:\t{0} of {1} ({2})".FormatString(count.ToString("N0"), total.ToString("N0"), (count / (decimal)total).ToString("P2")));
Which causes a lot of flickering.
Try Console.SetCursorPosition. More details here: How can I update the current line in a C# Windows Console App?
static void Main(string[] args)
{
Console.SetCursorPosition(0, 0);
Console.Write("################################");
for (int row = 1; row < 10; row++)
{
Console.SetCursorPosition(0, row);
Console.Write("# #");
}
Console.SetCursorPosition(0, 10);
Console.Write("################################");
int data = 1;
System.Diagnostics.Stopwatch clock = new System.Diagnostics.Stopwatch();
clock.Start();
while (true)
{
data++;
Console.SetCursorPosition(1, 2);
Console.Write("Current Value: " + data.ToString());
Console.SetCursorPosition(1, 3);
Console.Write("Running Time: " + clock.Elapsed.TotalSeconds.ToString());
Thread.Sleep(1000);
}
Console.ReadKey();
}
I know this question is a bit old but I found if you set Console.CursorVisible = false then the flickering stops as well.
Here's a simple working demo that shows multi-line usage without flickering. It shows the current time and a random string every second.
private static void StatusUpdate()
{
var whiteSpace = new StringBuilder();
whiteSpace.Append(' ', 10);
var random = new Random();
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var randomWord = new string(Enumerable.Repeat(chars, random.Next(10)).Select(s => s[random.Next(s.Length)]).ToArray());
while (true)
{
Console.SetCursorPosition(0, 0);
var sb = new StringBuilder();
sb.AppendLine($"Program Status:{whiteSpace}");
sb.AppendLine("-------------------------------");
sb.AppendLine($"Last Updated: {DateTime.Now}{whiteSpace}");
sb.AppendLine($"Random Word: {randomWord}{whiteSpace}");
sb.AppendLine("-------------------------------");
Console.Write(sb);
Thread.Sleep(1000);
}
}
The above example assumes your console window is blank to start. If not, make sure to use Console.Clear() first.
Technical Note:
SetCursorPosition(0,0) places the cursor back to the top (0,0) so the next call to Console.Write will start from line 0, char 0. Note, it doesn't delete the previous content before writing. As an example, if you write "asdf" over a previous line such as "0123456", you'll end up with something like "asdf456" on that line. For that reason, we use a whiteSpace variable to ensure any lingering characters from the previous line are overwritten with blank spaces. Adjust the length of the whiteSpace variable to meet your needs. You only need the whiteSpace variable for lines that change.
Personal Note:
For my purposes, I wanted to show the applications current status (once a second) along with a bunch of other status information and I wanted to avoid any annoying flickering that can happen when you use Console.Clear(). In my application, I run my status updates behind a separate thread so it constantly provides updates even though I have numerous other threads and long running tasks going at the same time.
Credits:
Thanks to previous posters and dtb for the random string generator used in the demo.
How can I generate random alphanumeric strings in C#?
You could try to hack something together using the core libraries.
Rather than waste your time for sub-standard results, I would check out this C# port of the ncurses library (which is a library used for formatting console output):
Curses Sharp
I think you can use \r in Windows console to return the beginning of a line.
You could also use SetCursorPosition.
I would recommend the following extension methods. They allow you to use a StringBuilder to refresh the console view without any flicker, and also tidies up any residual characters on each line
The Problem: The following demo demonstrates using a standard StringBuilder, where updating lines that are shorter than the previously written line get jumbled up. It does this by writing a short string, then a long string on a loop:
public static void Main(string[] args)
{
var switchTextLength = false;
while(true)
{
var sb = new StringBuilder();
if (switchTextLength)
sb.AppendLine("Short msg");
else
sb.AppendLine("Longer message");
sb.UpdateConsole();
switchTextLength = !switchTextLength;
Thread.Sleep(500);
}
}
Result:
The Solution: By using the extension method provided below, the issue is resolved
public static void Main(string[] args)
{
var switchTextLength = false;
while(true)
{
var sb = new StringBuilder();
if (switchTextLength)
sb.AppendLineEx("Short msg");
else
sb.AppendLineEx("Longer message");
sb.UpdateConsole();
switchTextLength = !switchTextLength;
Thread.Sleep(500);
}
}
Result:
Extension Methods:
public static class StringBuilderExtensions
{
/// <summary>
/// Allows StrinbBuilder callers to append a line and blank out the remaining characters for the length of the console buffer width
/// </summary>
public static void AppendLineEx(this StringBuilder c, string msg)
{
// Append the actual line
c.Append(msg);
// Add blanking chars for the rest of the buffer
c.Append(' ', Console.BufferWidth - msg.Length - 1);
// Finish the line
c.Append(Environment.NewLine);
}
/// <summary>
/// Combines two StringBuilders using AppendLineEx
/// </summary>
public static void AppendEx(this StringBuilder c, StringBuilder toAdd)
{
foreach (var line in toAdd.ReadLines())
{
c.AppendLineEx(line);
}
}
/// <summary>
/// Hides the console cursor, resets its position and writes out the string builder
/// </summary>
public static void UpdateConsole(this StringBuilder c)
{
// Ensure the cursor is hidden
if (Console.CursorVisible) Console.CursorVisible = false;
// Reset the cursor position to the top of the console and write out the string builder
Console.SetCursorPosition(0, 0);
Console.WriteLine(c);
}
}
I actually had this issue so I made a quick simple method to try and eliminate this.
static void Clear(string text, int x, int y)
{
char[] textChars = text.ToCharArray();
string newText = "";
//Converts the string you just wrote into a blank string
foreach(char c in textChars)
{
text = text.Replace(c, ' ');
}
newText = text;
//Sets the cursor position
Console.SetCursorPosition(x, y);
//Writes the blank string over the old string
Console.WriteLine(newText);
//Resets cursor position
Console.SetCursorPosition(0, 0);
}
It actually worked surprisingly well and I hope it may work for you!
Naive approach but for simple applications is working:
protected string clearBuffer = null; // Clear this if window size changes
protected void ClearConsole()
{
if (clearBuffer == null)
{
var line = "".PadLeft(Console.WindowWidth, ' ');
var lines = new StringBuilder();
for (var i = 0; i < Console.WindowHeight; i++)
{
lines.AppendLine(line);
}
clearBuffer = lines.ToString();
}
Console.SetCursorPosition(0, 0);
Console.Write(clearBuffer);
Console.SetCursorPosition(0, 0);
}
Console.SetCursorPosition(0, 0); //Instead of Console.Clear();
WriteTitle();
Console.WriteLine();
Console.WriteLine("Deleting:\t{0} of {1} ({2})".FormatString(count.ToString("N0")
I am trying to write code in J2ME for the Nokia SDK (S60 device) and am using Eclipse.
The code tries to play some wav files placed within the "res" directory of the project. The code is as follows:
InputStream in1 = null;
System.out.println("ABout to play voice:" + i);
try {
System.out.println("Getting the resource as stream.");
in1 = getClass().getResourceAsStream(getsound(i));
System.out.println("Got the resouce. Moving to get a player");
}
catch(Exception e) {
e.printStackTrace();
}
try {
player = Manager.createPlayer(in1, "audio/x-wav");
System.out.println("Created player.");
//player.realize();
//System.out.println("Realized the player.");
if(player.getState() != player.REALIZED) {
System.out.println("The player has been realized.");
player.realize();
}
player.prefetch();
System.out.println("Fetched player. Now starting to play sound.");
player.start();
in1.close();
int i1 = player.getState();
System.out.println("Player opened. Playing requested sound.");
//player.deallocate();
//System.out.println("Deallocated the player.");
}
catch(Exception e) {
e.printStackTrace();
}
}
Where the function getSound returns a string that contains the name of the file to be played. It is as follows:
private String getSound(int i) {
switch(i) {
case 1: return "/x1.wav";
case 2: return "/x2.wav";
}
}
My problem is this:
1. When I try to add more than 10 sounds, the entire application hangs right before the prefetch() function is called. The entire system slows down considerably for a while. I then have to restart the application.
I have tried to debug this, but have not gotten any solutions so far. It would be great if I could get some help on this.
The problem lies in the emulator being used for the project. In the emulation tab in the Run Configurations window, the following Device must be selected:
Group: Nokia N97 SDK v1.0
Device: S60 Emulator
Changing to the above from Devices listed under the Sun Java Wireless Toolkit solved the problem.