I want to achieve the following but so far, no luck
Open a file in the SD Card when the android application first started.
Stream the logcat output to the file.
When the application exits, stop the logcat streaming.
In my ApplicationClass extends Application onCreate() method, I do this
wwLogManager.openLogFile();
and here's the code in the openLogFile()
private static final String LOGCAT_COMMAND = "logcat -v time -f ";
String timestamp = Long.toString(System.currentTimeMillis());
String logFileName = BuildConstants.LOG_LOCATION + "_" + timestamp + ".log";
mLogFile = new File(Environment.getExternalStorageDirectory() + logFileName);
mLogFile.createNewFile();
String cmd = LOGCAT_COMMAND + mLogFile.getAbsolutePath();
Runtime.getRuntime().exec(cmd);
I do get log files in the sd card, but the log output in these files do not have any trace of the Log.i() calls that I placed in my activities. Is the logcat command that I used here correct? Thanks!
I apologize if I am misunderstanding your goals, but perhaps you could use the java.util.logging API instead of using Logcat or the Android Logging mechanism.
Like the Android logging API, the java.util.logging API allows you to easily log messages at various levels, such as FINE, FINER, WARN, SEVERE, etc.
But the standard logging API has additional advantages, too. For example, you can easily create a log file by using a FileHandler. In fact, FileHandler has a built-in log rotation mechanism, so you don't have to worry (so much) about cleaning up the log files. You can also create a hierarchy of Loggers; so, for example, if you have two Loggers, com.example.foo and com.example.foo.bar, changing the logging level of the former will also change the logging level of the latter. This will even work if the two Loggers are created in different classes! Moreover, you change logging behavior at runtime by specifying a logging configuration file. Finally, you can customize the format of the log by implementing your own Formatter (or just use the SimpleFormatter to avoid the default XML format).
To use the standard logging API, you might try something like this:
// Logger logger is an instance variable
// FileHandler logHandler is an instance variable
try {
String logDirectory =
Environment.getExternalStorageDirectory() + "/log_directory";
// the %g is the number of the current log in the rotation
String logFileName = logDirectory + "/logfile_base_name_%g.log";
// ...
// make sure that the log directory exists, or the next command will fail
//
// create a log file at the specified location that is capped 100kB. Keep up to 5 logs.
logHandler = new FileHandler(logFileName, 100 * 1024, 5);
// use a text-based format instead of the default XML-based format
logHandler.setFormatter(new SimpleFormatter());
// get the actual Logger
logger = Logger.getLogger("com.example.foo");
// Log to the file by associating the FileHandler with the log
logger.addHandler(logHandler);
}
catch (IOException ioe) {
// do something wise
}
// examples of using the logger
logger.finest("This message is only logged at the finest level (lowest/most-verbose level)");
logger.config("This is an config-level message (middle level)");
logger.severe("This is a severe-level message (highest/least-verbose level)");
The Android logging mechanism is certainly easy and convenient. It isn't very customizable, though, and log filtering must be done with tags, which can easily become unwieldy. By using the java.uitl.logging API, you can avoid dealing with a multitude of tags, yet easily limit the log file to specific parts of your application, gain greater control over the location and appearance of the log, and even customize logging behavior at runtime.
I repost my answer here so #JPM and others can see... The code basically just execute the logcat command and then build the log from the input stream.
final StringBuilder log = new StringBuilder();
try {
ArrayList<String> commandLine = new ArrayList<String>();
commandLine.add("logcat");
commandLine.add("-d");
ArrayList<String> arguments = ((params != null) && (params.length > 0)) ? params[0] : null;
if (null != arguments){
commandLine.addAll(arguments);
}
Process process = Runtime.getRuntime().exec(commandLine.toArray(new String[0]));
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = bufferedReader.readLine()) != null){
log.append(line);
log.append(LINE_SEPARATOR);
}
}
catch (IOException e){
//
}
return log;
Try manually setting a filter as described here:
http://developer.android.com/guide/developing/debugging/debugging-log.html#filteringOutput
Something like:
logcat ActivityManager:I MyApp:V *:S
If you replace "MyApp" with the log tags that you are using, that should show you all info (and greater) logs from ActivityManager, and all verbose (and greater) logs from your app.
I know this is a late answer to the question but I would highly recommend using Logback to write messages to a log file as well as the logcat.
Copy logback-android-1.0.10-2.jar and slf4j-api-1.7.5.jar to your libs folder.
Right-Click on both libs and from the menu select Build Path -> Add to Build Path.
Create a logback.xml file in your assets folder and enter the following:
%msg
WARN
${LOG_DIR}/log.txt
%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
To write a log:
public class MyActivity extends Activity
{
public static final Logger logger = LoggerFactory.getLogger(MyActivity.class);
protected void onCreate(Bundle b)
{
super(b);
try{
throw new Exception("Test");
}catch(Exception e){
logger.error("Something bad happened",e);
}
}
}
Related
Making app in Unity.
App works perfectly in Unity editor:
can access firebase for user login - this isnt the issue
can read and write from/to google sheet located in google drive using service account
When I build to android (apk file), and install on physical andoid device (Samsung S20 phone):
can access firebase for user login - so it is not an network/internet problem
CANT read/write from google sheet.
A portion of my code is here:
Authorisation - i am not sure if this bit works on the phone, or how to check.
public void Auth() // authorise access to the googlesheet online
{
//jsonKey = File.ReadAllText("Assets/Resources/Creds/beerhats-db-3***.json"); // location of key - read it - save to string
TextAsset txtAsset = (TextAsset)Resources.Load("beerhats-db-3***", typeof(TextAsset)); //i changed the file name here on stackoverflow just in case its a security thing
string jsonKey = txtAsset.text;
ServiceAccountCredential.Initializer initializer = new ServiceAccountCredential.Initializer(Secrets.serviceAccountID);
var jsonData = (JObject)JsonConvert.DeserializeObject(jsonKey);
if (jsonData != null) // the json file isnt moving or changing - so probably dont need an if statemet - remove later
{
string privateKey = jsonData["private_key"].Value<string>(); // specifically get the private key from all the data in the json file
ServiceAccountCredential credential = new ServiceAccountCredential(initializer.FromPrivateKey(privateKey));
service = new SheetsService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
});
}
}
Part of my ReadFile code:
public async Task<string> ReadFile(string sheetName, string cellLocation) // for reading data only
{
// creates a string of location to write to
string whereToRead = sheetName + "!" + cellLocation;
SpreadsheetsResource.ValuesResource.GetRequest request = service.Spreadsheets.Values.Get(Secrets.spreadsheetID, whereToRead);
StringBuilder sb = new StringBuilder();
ValueRange response = await request.ExecuteAsync(); // run this on a separate thread as it takes long?
IList<IList<object>> values = response.Values;
On the phone, it executes the stringbuilder line, but not the executeasync() line.
Tried:
upgrade Unity version
change the min and target API levels
introduced keystore and project keys
introduced async incase it was a loading issue
change custom gradle template checkboxes
change read access on android sdk
update nuget installs of google apis
asking chatgpt for help
looking at various forums for similar issues
I am not running on an emulator, so no help with errors during run time. No errors in editor when built.
Expecting:
when installed on android device, the app to read/write from google sheet located in google drive
Requesting:
ideas to try to get this working! Thankyou :)
I am learning logging in android code using android studio and emulator
I found that the following command shows a traceback with hyperlink to the code location
Log.d("TAG", "Message with stack trace info", new Throwable());
the image of logcat with hyperlink is
How can i create only the hyperlink part in my log message, without any traceback output
Try this, for example:
import android.util.Log;
public class Logger {
public static void log(String tag, String message) {
String caller = getCallerInfo(new Throwable().getStackTrace());
Log.d(tag, message + caller);
}
private static String getCallerInfo(StackTraceElement[] stacks) {
if (stacks == null || stacks.length < 1) {
return "";
}
StackTraceElement stack = stacks[1];
return String.format(" (%s:%s)", stack.getFileName(), stack.getLineNumber());
}
}
And call it from any where in your code
Logger.log("Manowar", "Today is the good day to die");
As of now the answer by #Cao Mạnh Quang was not giving me the Hyperlink.
The specific String format required for it's generation is this:
return String.format(" %s(%s:%s)", traceE.getClassName(), traceE.getFileName(), traceE.getLineNumber());
which is just the same as:
return stackTraceElement.toString();
so you may as well just do that.
Nothing was working for me...
My guess is that...
This hyperlink is generated by a preconfigured String specification format.
this format follows the className + "(" + fileName + ":" + lineNumber + ")"
If any of those parameters are missing, the hyperlink will not be generated.
There are a couple questions that arise from this:
Is this specification hard coded as a consensus of each LogCat display (IDE side interacts directly with String)
OR
Is this specification hardcoded into the Java code itself? (Java side interprets String generates hyperlink signal + IDE side interprets hyperlink signal and generates it)
The difference between which of these options is the one, would imply whether hyperlink generation is possible simply by changing the required configuration for the Logcat to generate the link either at IDE config level... OR at Java level.
Maybe it is not possible, and this configuration format cannot be changed....
Btw I am sure there must be some super hacky way to achieve this, maybe a way not so intuitive... or maybe it just requires some digging on the IDE config options...
I'm building an app with the Entity Framework on Xamarin that lets me compare some data. But when I start my "fetchdata" function, I receive the Error:
System.Data.SqlClient.SqlException (0x80131904): Snix_Connect (provider: SNI_PN7, error: 35 - SNI_ERROR_35)Snix_Connect (provider: SNI_PN7, error: 35 - SNI_ERROR_35)
I see many posts about Xamarin / Android & that it is not possible to get a connection to a SQL Server. Is there any way to fetch data from a SQL Server with .NET Core on Xamarin?
This is the string I put into SQL_Class folder with Sql_Common.cs
Fill up the brace brackets with actual parameters (removing the brace brakets too).
public static string SQL_connection_string = #"data source={server_address};initial catalog={database_name};user id={user_id};password={password};Connect Timeout={seconds}";
Then I access whenever I need it from any xamarin code just like we use in our asp.net c#
This works for me on my app without any issues.
using (SqlConnection Sql_Connection = new SqlConnection(Sql_Common.saralEHR_connection_string))
But as #Jason mentioned in his first reply, I too would get once again check the security part. I fexperienced before publishing Package to Google Play, they encrypt the App files with Hash Key Code and then only it gets upload to server
Yes it is possible (HuurrAYY!):
Im new in .net core, c# and so on and for me it was a hell of a work to get it working..
So here for the other noobs who are seeking for Help:
Guide´s i used:
Building Android Apps with Entity Framework
https://medium.com/#yostane/data-persistence-in-xamarin-using-entity-framework-core-e3a58bdee9d1
https://blog.xamarin.com/building-android-apps-entity-framework/
Scaffolding
https://cmatskas.com/scaffolding-dbcontext-and-models-with-entityframework-core-2-0-and-the-cli/
How i did it:
Build your normal Xamarin app.
create new .net solution like in the tutorials (DONT WRITE YOUR Entity Framework CLASSES)
create a third solution what has to be a .net core console application
Scaffold your DB in your CONSOLE application move all created classes & folders in your "xamarin .net" solution & change the namespaces
Ready to Go!
Side Node: NuGets you need in every solution:
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.SqlServer
[EDIT: NuGets you need in every solution]
I am doing this way (working snippet):
string connectionString = #"data source={server};initial catalog={database};user id={user};password={password};Connect Timeout=10";
string databaseTable = "{table name}";
string selectQuery = String.Format("SELECT count(*) as Orders FROM {0}", databaseTable);
try
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
//open connection
connection.Open();
SqlCommand command = new SqlCommand(selectQuery, connection);
command.Connection = connection;
command.CommandText = selectQuery;
var result = command.ExecuteScalar().ToString();
//check if there is result
if(result != null)
{
OrdersLabel.Text = result;
}
}
}
catch (Exception ex)
{
OrdersLabel.Text = ex.Message;
}
It is working fine, but API call more elegant.
I hope it helps.
public static String[] getAdbLogCat() {
try {
String line;
ArrayList<String> arrList = new ArrayList<String>();
Process p = Runtime.getRuntime().exec("D:/androidsoftware/android sdk/platform-tools/adb shell logcat");
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = br.readLine()) != null) {
System.out.println(line);
Log.e("ADB TEST",line);
}
return (String[])arrList.toArray(new String[0]);
} catch (IOException e) {
System.err.println(e);
e.printStackTrace();
return new String[]{};
}
}
Environment null is coming after executing this method.I am running this in emulator.What if i want to run in mobile then what will be the adb path? My requirement is to read the adb log and save the crash data into a table.My android sdk located in d drive.Or is there any other way to get my application crash log from android system log.
You can't run executable programs on your computer from within an app running on an emulator. You can only run programs that live in the emulator's own space. The emulator is like an actual device, and you would never expect a device to reach outside itself to execute some other process.
You need a bridge to contact the host-environment from your android application.
Sample project: https://github.com/toantran-ea/adb-ci-bridge
You can extend the function with new endpoint in that library. And make call to from your application.
Sample request with curl:
curl -H "Content-Type: application/json" -X POST -d '{"tag":"sample tag value","trace":"TooAwesomeException foo bar"}' http://localhost:9001/screenshot
This is used in some limited contexts, like when you running on a Continuous Sever and you need some utility functions to contact with host (for screenshot, reporting, or something else).
I'm using JDOM with my Android project, and every time I get a certain set of characters in my server response, I end up with these error messages:
05-04 10:08:46.277: E/PARSE: org.jdom.input.JDOMParseException: Error on line 95 of document UTF-8: At line 95, column 5263: unclosed token
05-04 10:08:46.277: E/Error Handler: Handler failed: org.jdom.input.JDOMParseException: Error on line 1: At line 1, column 0: syntax error
When I make the same query through google chrome, I can see that all of the XML came through fine, and that there are in fact no areas where a token is not closed. I have run into this problem several times throughout the development of the application, and the solution has always been to remove odd ascii characters (copyright logos, or trademark characters, etc. that got copied/pasted into those data fields). How can I get it to either a remove those characters, or b strip them and continue the function. Here's an example of one of my parse functions.
public static boolean parseUserData(BufferedReader br) {
SAXBuilder builder = new SAXBuilder();
Document document = null;
try {
document = builder.build(br);
/* XML Output to Logcat */
if (document != null) {
XMLOutputter outputter = new XMLOutputter(
Format.getPrettyFormat());
String xmlString = outputter.outputString(document);
Log.e("XML", xmlString);
}
Element rootNode = document.getRootElement();
if (!rootNode.getChildren().isEmpty()) {
// Do stuff
return true;
}
} catch (Exception e) {
GlobalsUtil.errorUtil
.setErrorMessage("Error Parsing XML: User Data");
Log.e(DEBUG_TAG, e.toString());
return false;
}
}
It distinctly sounds like a character encoding issue. I think duffymo is correct in his assessment. I have two comments though ....
If you are getting your data through a URL you should be using the URLConnection.getContentType() to get the charset (if it is set and the charset is not null) to set up the InputStreamReader on the URL's InputStream...
Have you tried JDOM 2.0.1? It is the first JDOM version that is fully tested on Android... (and the only 'supported' JDOM version on Android). JDOM 2.0.1 also has a number of performance tweaks, and memory optimizations that should make your processing faster. It also fixes a number of bugs.... though from what I see you should not run in to any bug problems.....
Check out https://github.com/hunterhacker/jdom/wiki/JDOM2-Migration-Issues and https://github.com/hunterhacker/jdom/wiki/JDOM2-and-Android
Is the BufferedReader constructed to take the encoding argument? Perhaps you need to tell the Reader or InputStream that you pass to use UTF-8.