I'm trying to create a custom Debug Tree class to get the same result as the following:
I have followed this Stackoverflow answer:
Log method name and line number in Timber
But using that answer gives me two problems:
Implementing the custom Debug Tree class does not log anything when I use more than one method.
public class MyDebugTree extends Timber.DebugTree {
#Override
protected String createStackElementTag(StackTraceElement element) {
return String.format("(%s:%s)#%s",
element.getFileName(),
element.getLineNumber(),
element.getMethodName());
}
}
public class BaseApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
if (BuildConfig.DEBUG) {
Timber.plant(new MyDebugTree);
}
}
}
The above causes it to not log at all.
If I use only return element.getFileName(); it successfully logs that one error.
The second problem I'm having is that using a custom DebugTree class does not give me the same results as using err.getStackTrace()[0].getLineNumber().
}, err -> {
Timber.e("Method name: " + err);
Timber.e("Method name: " + err.getStackTrace()[0].getMethodName());
}
The custom Debug Tree class does not display the name of the method I'm trying to log.
Why is it not logging when I use all three methods?
Also how can I get it to log like it would using
err.getStackTrace()[0].getMethodName()?
I'm using 'com.jakewharton.timber:timber:4.7.1'
You seem to be doing it right. I recreated your code in kotlin (programming language should not matter) and i was able to show my logs.
MyDebugTree.kt
class QueenlyDebugTree : Timber.DebugTree() {
override fun createStackElementTag(element: StackTraceElement): String {
return "(${element.fileName}:${element.lineNumber})#${element.methodName}"
}
}
force log using an actual exception:
try {
throw RuntimeException("Hello World")
} catch (e: Exception) {
Timber.e(e)
}
i got a log:
So, from what i saw from your code, its most probably because you have a compact logcat view. To update your logcat view, follow these steps:
1. Make sure you have standard view selected
2. Configure standard view
3. Make sure Show tags is selected and tag column is at max(35)
Related
I am trying to override the default behavior of the Android button renderer in Xamarin Forms. I have leveraged (not stolen;) the source code from https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/visual/create and have created this:
namespace Patron.Droid.Renderers
{
public class MixedCaseButtonRenderer : Xamarin.Forms.Platform.Android.AppCompat.ButtonRenderer
{
public MixedCaseButtonRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Button> el)
{
base.OnElementChanged(el);
if (el.OldElement != null)
{
// Cleanup
}
if (el.NewElement != null)
{
var button = (Button)this.Control;
button.SetAllCaps(false);
}
}
}
}
But when I build it, I get the following errors
Severity Code Description Project File Line Suppression State
Error CS0115 'MixedCaseButtonRenderer.OnElementChanged(ElementChangedEventArgs<Button>)': no suitable method found to override Patron.Android C:\Users\ThomH\workspace\patron\Patron\Patron\Patron.Android\Renderers\MixedCaseButtonRenderer.cs 22 Active
Error CS0311 The type 'Android.Widget.Button' cannot be used as type parameter 'TElement' in the generic type or method 'ElementChangedEventArgs<TElement>'. There is no implicit reference conversion from 'Android.Widget.Button' to 'Xamarin.Forms.Element'. Patron.Android C:\Users\ThomH\workspace\patron\Patron\Patron\Patron.Android\Renderers\MixedCaseButtonRenderer.cs 22 Active
Error CS1503 Argument 1: cannot convert from 'Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Android.Widget.Button>' to 'Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Xamarin.Forms.Button>' Patron.Android C:\Users\ThomH\workspace\patron\Patron\Patron\Patron.Android\Renderers\MixedCaseButtonRenderer.cs
Button exists in both Android.Widget and Xamarin.Forms. You need to specify which namespace you mean to use
I have this array of values that are considered wrong
public static final String[] WRONG_VALUES = {"1000","4000","2000"};
In my test I am clicking on the edit text, inserting the text and pressing back to close the keyboard.
onView(withId(R.id.inputField)).perform(click(), replaceText(text), pressBack());
and then check if the error view is showing
onView(withId(R.id.error)).matches(not(isCompletelyDisplayed()));
This is working but I would like output somewhere in the test log the value which it failed for because when the test does fail I do not know which value was being tested
Is this possible?
Thanks
You can implement the FailureHandler interface to define custom failure handling for Espresso:
public class CustomFailureHandler implements FailureHandler {
private final FailureHandler delegate;
public CustomFailureHandler(#NonNull Instrumentation instrumentation) {
delegate = new DefaultFailureHandler(instrumentation.getTargetContext());
}
#Override
public void handle(final Throwable error, final Matcher<View> viewMatcher) {
// Log anything you want here
// Then delegate the error handling to the default handler which will throw an exception
delegate.handle(error, viewMatcher);
}
}
Before your tests are running, create and set the custom error handler like this:
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
Espresso.setFailureHandler(new CustomFailureHandler(instrumentation));
You can even log your custom messages for particular assertions by catching their Exception and throwing your own instead like:
try {
onView().check() // Some test here
} catch (Exception ex) {
throw new Exception("This test failed with this custom message logged: " + ex.getMessage());
}
Kotlin translation of thaussma's response
class CustomFailureHandler(instrumentation: Instrumentation) : FailureHandler {
var delegate: DefaultFailureHandler = DefaultFailureHandler(instrumentation.targetContext)
override fun handle(error: Throwable?, viewMatcher: Matcher<View>?) {
// Log anything you want here
// Then delegate the error handling to the default handler which will throw an exception
delegate.handle(error, viewMatcher)
}
}
I have three Android projects: BaseLibProject, MainLibProject, AppProject.
The relationship of these three Android projects is that:
The BaseLibProject is a library project used by MainLibProject.
The MainLibProject uses BaseLibProject as library project, and generates MainLib.jar(use maven build)
The generated MainLib.jar is added to AppProject's libs/ folder & also added to the build path of AppProject.
NEXT:
A simple class in BaseLibProject :
public class BaseLibClass {
public static String doBaseTask() {
Log.i("MyLog", "doBaseTask..."); //I can't see this log
return "Result from Base!";
}
}
A simple class in MainLibProject which defined a function invokes the function in BaseLibProject:
public class MainLibClass {
public static void doMainTask() {
Log.i("MyLog", "doMainTask..."); //I can see this log in logcat
String result = BaseLibClass.doBaseTask();
Log.i("MyLog", "result = " + result); //I can see the result log
}
}
Finally, in my AppProject I simply call above function of MainLibProject (remember I have MainLib.jar):
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MainLibClass.doMainTask();
}
}
I started logcat with command adb logcat -s MyLog:* . When I run my AppProject application, logcat displays
I/MyLog(2039): doMainTask...
I/MyLog(2039): result = Result from Base!
According to above log, the code in BaseLibProject is running (because I got result from BaseLibClass), but it doesn't display any logs from BaseLibProject, why???
(I have googled on internect, someone got similar issue fixed by restarting eclipse, but in my case, it doesn't help. Besides, I am checking logs from terminal NOT from eclipse.)
Ok, finally, I fixed the problem.
The reason is that in BaseLibProject pom.xml, I defined <packaging>apk</packaging>, while in MainLibProject pom.xml, when I define the dependency of BaseLibProject, I didn't specify the <type> of the artifact.
After I changed BaseLibProject's pom.xml to <packagin>apklib</packaging> and in MainLibProject's pom.xml specified the dependency of BaseLibProject with <type>apklib</type> . I am able to see the logs in BaseLibProject.
I've just started to write an application.
I want to create a custom Exception class that spans over my whole application.
Want to do this so that every exception can be passed to that class file & whenever a exception is occurred, the Logs can be stored in one place.
I tired using this, but it does not seems an entirely good practice.
What is the best method to achieve this
Thank You
You could try just making a general (non-Exception) class, and pass the exception to it. Something like this should work:
Public Class ExceptionHandler {
public ExceptionHandler() {
}
public static handle(Exception e) {
// do stuff
}
}
in your code:
try {
}
catch(Exception e) {
ExceptionHandler.handle(e);
}
I'm currently trying to develop an application under Android using Mono.
I'd like to add support for plugins to my application so additional features could be brought to it.
I was able to load simple .dll at runtime in my program, however whenever I try creating a dll implementing both my interface and a custom activity, an exception of type Java.Lang.NoClassDefFoundError is thrown.
There is the class inside the dll code:
[Activity (Label = "Vestiaire")]
public class Vestiaire : Activity, IModule
{
public string Name { get; set; }
public string Version { get; set; }
void OnClickVestiaireButton(object sender, System.EventArgs e)
{
;
}
public void InitVestiaireModule()
{
Run();
}
public Type LaunchActivity ()
{
return typeof(Vestiaire);
}
public void Init()
{
Name = "Vestiaire Module";
Version = "0.1";
}
public void Run()
{
}
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
}
}
The line responsible for the exception: (from the program core)
LoadedPlugin.Add((IModule)(Activator.CreateInstance(Plugin)));
Things I'm actually wonderring are:
- Is it possible to actually achieve what i'm trying to ?
If yes, help would be apreciated on that problem :P
Otherwise what would be the best alternative ?
Global point is to be able to load a custom menu at runtime loaded from a dll.
Thanks.
i think the key to your problem is that the Activity needs to be registered in you Manifest.xml file.
For Activities in you main app, MonoDroid does this for you - but I don't think this will work for your plugin.
Things you could try are:
putting the Activity in the Manifest yourself (MonoDroid does seem very capable at merging these files)
if that doesn't work, then you could try using a Fragment instead - and loading the Fragment into a custom FragmentActivity in your main app.