Log.i("Test", "Hello, Log")
Timber.i("Hello, Timber")
I can see the Log.i log in Debug console and Logcat, I don't see the Timber log in anywhere.
I/Test: Hello, Log
I'm building in stagingDebug mode. (I have 4 options, production debug and release and staging debug and release)
What I'm missing?
Make sure that you have initialised Timber in Application class. Following code might help :-
public class MyApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
// This will initialise Timber
if (BuildConfig.DEBUG) {
Timber.plant(new Timber.DebugTree());
}
}
}
If you're initializing Timber like this:
if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
}
Be sure, that you're imported BuildConfig from your app package, and not something like BuildConfig's from 3rd party libraries like this: import org.koin.android.BuildConfig. I strugled with this a few times.
initialization Timber in Kotlin
class ExampleApplication : Application(){
override fun onCreate() {
super.onCreate()
// init timber
if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
}
}
}
and don't forget write android:name of Application in Manifest.xml:
<application
android:name=".ExampleApplication"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.PostMakerMassive">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
In my case, I imported the incorrect BuildConfig. You can check if that is the issue with yours as well.
Try to add tag in Timber. It should be set (automatically) based on the information in the Manifest, but it does not always happen (e.g. for custom devices with custom OS)
So first of all plant it:
// Java
Timber.plant(new Timber.DebugTree());
// Kotlin
Timber.plant(Timber.DebugTree())
and next set tag:
// custom tag
Timber.tag("your custom tag");
// or
Timber.tag("trolololololo");
// or something (more serious) from strings:
Timber.tag(getString(R.string.app_name))
Related
I am having problem trying to initialize my WorkerGetData class for instrumentation testing. I have done the following:
removed the default work initializer in manifest file.
added configuration provider in the Application class.
called WorkManagerTestInitHelper in the Test file.
added kapt "androidx.hilt:hilt-compiler:1.0.0" to app module.
added kapt "com.google.dagger:hilt-compiler:2.42" to app module.
But still get the error java.lang.NoSuchMethodException: com.example.myproject.WorkerGetData.<init> [class android.content.Context, class androidx.work.WorkerParameters].
I am using work manager version 2.7.1.
Code
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>
#HiltAndroidApp
class Application : android.app.Application(), Configuration.Provider {
#Inject
lateinit var workerFactory: HiltWorkerFactory
override fun getWorkManagerConfiguration() =
Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
override fun onCreate() {
super.onCreate()
}
}
#HiltWorker
class WorkerGetData #AssistedInject constructor(
val repository: MyRepository,
#Assisted val context: Context,
#Assisted workerParameters: WorkerParameters,
): CoroutineWorker(context, workerParameters) {
override suspend fun doWork(): Result {
val data = repository.getData()
return Result.success(data)
}
}
#Test
fun testGetDataWorker() {
val request = OneTimeWorkRequestBuilder<WorkerGetData>()
.build()
val workManager = WorkManager.getInstance(context)
workManager.enqueue(request).result.get() /*<-----------------------error here*/
val workInfo = workManager.getWorkInfoById(request.id).get()
assertThat(workInfo.state).isEqualTo(WorkInfo.State.SUCCEEDED)
}
There was a 6th item which I had forgot to do. I needed to create a WorkerFatory() so that Hilt could correctly inject WorkerGetData constructor. There is a great article from Pietro Maggi on how to do this:
https://medium.com/androiddevelopers/customizing-workmanager-with-dagger-1029688c0978
i have implement the geolocation Plugin like the instruction says, but when i wanted to use Geolocation.isLocationOperational(). The Method isn't defined.
The Quellcode where i use it:
import 'package:geolocation/geolocation.dart';
import 'dart:async';
void checkGPS() async{
final GeolocationResult result = await Geolocation.isLocationOperational();
if(result.isSuccessful) {
print("Success");
} else {
print("Fail");
}}
in the xml file i added the permission i needed.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
someone have a idea what i make wrong?
I have input complex big XML files for the Mule flow.
File end point-> Byte Array to String -> Splitter -> ....
I have got org.xml.sax.SAXParseException: Content is not allowed in prolog when I try to process input files by using Splitter component. When I create new XML file and copy content of original file to the file, input files are processed.
I delete BOM marker when I create new file. Original file has EF BB BF since the beginning of the file, local file has not.
Mule config:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking"
xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml"
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans" version="EE-3.4.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mulesoft.org/schema/mule/file
http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans
current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.xsd
http://www.mulesoft.org/schema/mule/ee/tracking
http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd">
<mulexml:dom-to-xml-transformer name="domToXml"/>
<flow name="SplitterFlow1" doc:name="SplitterFlow1">
<file:inbound-endpoint path="D:\WORK\Input"
moveToDirectory="D:\WORK\Output"
responseTimeout="10000" doc:name="File" fileAge="200" encoding="UTF-8"/>
<byte-array-to-string-transformer doc:name="Byte Array to String" />
<splitter evaluator="xpath" expression="/Invoices/invoice"
doc:name="Splitter"/>
<transformer ref="domToXml" doc:name="Transformer Reference"/>
<tracking:custom-event event-name="Invoice ID" doc:name="Custom Business event">
</tracking:custom-event>
<logger level="INFO" doc:name="Logger"/>
<file:outbound-endpoint path="D:\WORK\Output"
outputPattern="#[function:dateStamp:dd-MM-yyyy-HH.mm.ss]-#[header:OUTBOUND:MULE_CORRELATION_SEQUENCE]"
responseTimeout="10000" doc:name="File"></file:outbound-endpoint>
</flow>
</mule>
Please advise me how I can do it in the Mule flow. Thank you in advance.
It's a pretty old post but here is my contribution.
Additionaly to the Java transformer approach suggested by #alexander-shapkin, I strongly recommend that you use Apache Commons' org.apache.commons.io.BOMInputStream to handle BOM marker out-of-the-box. The code would look something like below:
import java.io.InputStream;
import org.apache.commons.io.ByteOrderMark;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.BOMInputStream;
import org.mule.api.MuleMessage;
import org.mule.api.transformer.TransformerException;
import org.mule.transformer.AbstractMessageTransformer;
public class DeleteBOM extends AbstractMessageTransformer {
#Override
public Object transformMessage(MuleMessage message, String outputEncoding)
throws TransformerException {
try (InputStream in = new BOMInputStream(IOUtils.toInputStream(message.getPayloadAsString()), ByteOrderMark.UTF_8)) {
return IOUtils.toString(in);
} catch (Exception e) {
throw new RuntimeException("Could not remove BOM marker");
}
}
}
I partially reproduced your Mule app with the following configuration:
<file:connector name="File" autoDelete="false" streaming="true" validateConnections="true" doc:name="File" />
<mulexml:dom-to-xml-transformer name="DOM_to_XML" doc:name="DOM to XML"/>
<flow name="lalaFlow">
<file:inbound-endpoint path="D:\WORK\Input" moveToDirectory="D:\WORK\Output" responseTimeout="10000" doc:name="File" fileAge="200" encoding="UTF-8"/>
<component class="org.mule.bom.DeleteBOM" doc:name="Java"/>
<transformer ref="DOM_to_XML" doc:name="Transformer Reference"/>
...
</flow>
For further reference, go to https://commons.apache.org/proper/commons-io/javadocs/api-2.2/org/apache/commons/io/input/BOMInputStream.html
You can add before splitter an Java transformer with class:
package importxmltoapis;
import org.mule.api.MuleMessage;
import org.mule.api.transformer.TransformerException;
import org.mule.transformer.AbstractMessageTransformer;
public class DeleteBOM extends AbstractMessageTransformer{
public static final String BOM = "\uFEFF";
#Override
public Object transformMessage(MuleMessage message, String outputEncoding)
throws TransformerException {
String s="";
try {s = removeBOM(message.getPayloadAsString());} catch (Exception e) {e.printStackTrace();}
return s;
}
private static String removeBOM(String s) {
if (s.startsWith(BOM)) {
s = s.substring(1);
}
return s;
}
}
Try the following
1.Use the file to string transformer instead of bytearray to string transformer .
2.Check if you big xml is read completely and if not use the file age property of the file endpoint which will enable you to read your large file completely.
I have tree instance calling an iconFunction "getIconFromItem".
<mx:Tree dataProvider="{collection}" iconFunction="getIconFromItem" />
The getIconFromItem function is returning null even though the bitmap is not null.
public function getIconFromItem(item:Object):Class {
var result:Class = item.icon as Class ;
return result ;
}
Setting a break point on the return result line reveals that item.icon is a bitmap and result is null.
Any ideas or pointers on how to successfully cast a bitmap as class so that the bitmap is returned as an icon?
Cheers
Keith
The problem here is that item.icon is of type Bitmap, which is not extended from the type Class, but from Object. Whenever you cast to a type that is not in the object's type hierarchy, null is returned.
You want to get the class of the icon, which will be instantiated by the tree control, not the icon itself, so you should change your function to
public function getIconFromItem(item:Object):Class {
return item.icon.constructor as Class;
}
The issue was iconFunction expects a class. Each embedded image has a subclass automatically generated by the compiler. Thanks to #weltraumpirat for pointing me in the right direction :-)
The goal was to dynamically display icons in a tree class. It is possible to modify the class created by Ben Stucki (http://blog.benstucki.net/?p=42) to work with the TreeItemRenderer.data object but this failed when I created a custom MXTreeItemRenderer.
Ended up creating a BitmapImage and a custom TreeItemRenderer which used a prefined iconBitmap attribute within a class to dynamically load icons.
package components
{
import flash.display.BitmapData;
import mx.core.mx_internal;
import spark.core.IContentLoader;
import spark.primitives.BitmapImage;
public class RuntimeBitmapImage extends BitmapImage
{
public function RuntimeBitmapImage()
{
super();
}
public function set bitmapData(bitmapData:BitmapData):void
{
super.setBitmapData(bitmapData, false);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<s:MXTreeItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" >
<fx:Script>
<![CDATA[
override public function set data(value:Object):void {
super.data = value;
if ( value != null ) {
if ( value.iconBitmap != null ) {
runtimeBitmapImage.bitmapData = value.iconBitmap.bitmapData ;
}
}
}
]]>
</fx:Script>
<s:states>
<s:State name="normal" />
<s:State name="hovered" />
<s:State name="selected" />
</s:states>
<s:HGroup left="0" right="0" top="0" bottom="0" paddingTop="2" verticalAlign="middle">
<s:Rect id="indentationSpacer" width="{treeListData.indent}" percentHeight="100" alpha="0">
<s:fill>
<s:SolidColor color="0xFFFFFF" />
</s:fill>
</s:Rect>
<potentiate:RuntimeBitmapImage id="runtimeBitmapImage" left="2" width="18" />
<s:Label id="labelField" text="{treeListData.label}" paddingTop="2"/>
</s:HGroup>
</s:MXTreeItemRenderer>
I have a problem with i18n enums in my JSF application. When I started, I had enums with the text defined inside. But now, I have keys tied to message bundles in the enum.
Example one of my enums:
public enum OrderStatus implements CustomEnum {
PENDING("enum.orderstatus.pending"),
CANCELED("enum.orderstatus.canceled");
/**
* key in message bundle
*/
private String name;
OrderStatus(String name) {
this.name = name;
}
#Override
public String getName() {
return name;
}
}
In the view layer, I use something like:
<!-- input -->
<h:selectOneMenu value="#{order.status}">
<f:selectItems value="#{flowUtils.orderStatuses}"/>
</h:selectOneMenu>
<!-- output -->
<h:outputText value="#{order.status}"/>
and in Java:
public class FlowUtils {
public List<SelectItem> getOrderStatuses() {
ArrayList<SelectItem> l = new ArrayList<SelectItem>();
for(OrderStatus c: OrderStatus.values()) {
// before i18n
// l.add(new SelectItem(c, c.getName()));
// after i18n
l.add(new SelectItem(c, FacesUtil.getMessageValue(c.getName())));
}
return l;
}
}
public class FacesUtil {
public static String getMessageValue(String name) {
FacesContext context = FacesContext.getCurrentInstance();
return context.getApplication().getResourceBundle(context, "m").getString(name);
}
}
It worked well, but when I needed to output #{order.status}, I needed to convert it.
So I implemented a converter, but got in trouble with conversion of String to Object in the getAsObject() method.
web.xml:
<converter>
<converter-for-class>model.helpers.OrderStatus</converter-for-class>
<converter-class>model.helpers.EnumTypeConverter</converter-class>
</converter>
Java:
public class EnumTypeConverter implements Converter {
#Override
public Object getAsObject(FacesContext context, UIComponent comp,
String value) throws ConverterException {
// value = localized value :(
Class enumType = comp.getValueBinding("value").getType(context);
return Enum.valueOf(enumType, value);
}
#Override
public String getAsString(FacesContext context, UIComponent component,
Object object) throws ConverterException {
if (object == null) {
return null;
}
CustomEnum type = (CustomEnum) object;
ResourceBundle messages = context.getApplication().getResourceBundle(context, "m");
String text = messages.getString(type.getName());
return text;
}
}
I'm entangled now with that. Anybody know how to internationalize multiple Enums efficiently?
The value which is passed through the converter is not the option label as you seem to expect, but the option value. The best practice is to not do this in the model side, but in the view side, because the model shouldn't need to be i18n aware.
As to the approach, you're basically unnecessarily overcomplicating things. Since JSF 1.2 there's a builtin EnumConverter which will kick in automatically and since JSF 2.0 you can iterate over a generic array or List in f:selectItems by the new var attribute without the need to duplicate the values over a List<SelectItem> in the model.
Here's how the bean can look like:
public class Bean {
private OrderStatus orderStatus;
private OrderStatus[] orderStatuses = OrderStatus.values();
// ...
}
And here's how the view can look like (assuming that msg refers to the <var> as you've definied in <resource-bundle> in faces-config.xml):
<h:selectOneMenu value="#{bean.orderStatus}">
<f:selectItems value="#{bean.orderStatuses}" var="orderStatus"
itemValue="#{orderStatus}" itemLabel="#{msg[orderStatus.name]}" />
</h:selectOneMenu>
That's all.
Unrelated to the problem, you've typos in the enum name and message keys, it should be:
PENDING("enum.orderstatus.pending"),
CANCELLED("enum.orderstatus.cancelled");
And, more clean would be to keep the bundle keys out the enum and use enum itself as part of bundle key. E.g.
PENDING,
CANCELLED;
<h:selectOneMenu value="#{bean.orderStatus}">
<f:selectItems value="#{bean.orderStatuses}" var="orderStatus"
itemValue="#{orderStatus}" itemLabel="#{msg['enum.orderstatus.' += orderStatus]}" />
</h:selectOneMenu>
enum.orderstatus.PENDING = Pending
enum.orderstatus.CANCELLED = Cancelled
I have posted my solution here: Internationalization of multiple enums (translation of enum values) - but still hoping for further enhancement.
EDIT: with the help of #Joop Eggen, we have come up with a really cool solution:
EDIT again: complete and ready-to-use solution:
Make a class
public final class EnumTranslator {
public static String getMessageKey(Enum<?> e) {
return e.getClass().getSimpleName() + '.' + e.name();
}
}
Make it a custom EL function
<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
version="2.0">
<namespace>http://example.com/enumi18n</namespace>
<function>
<function-name>xlate</function-name>
<function-class>your.package.EnumTranslator</function-class>
<function-signature>String getMessageKey(java.lang.Enum)</function-signature>
</function>
</facelet-taglib>
Add the taglib to your web.xml
<context-param>
<param-name>javax.faces.FACELETS_LIBRARIES</param-name>
<param-value>/WEB-INF/enumi18n.taglib.xml</param-value>
</context-param>
Have properties files enum_en.properties and enum_yourlanguage.properties like this
TransferStatus.NOT_TRANSFERRED = Not transferred
TransferStatus.TRANSFERRED = Transferred
Add the properties files as resource bundles to your faces-config.xml
<resource-bundle>
<base-name>kk.os.obj.jsf.i18n.enum</base-name>
<var>enum</var>
</resource-bundle>
Add the custom taglib to your xhtml files
<html ... xmlns:l="http://example.com/enumi18n">
And - voilĂ - you can now access the translated enum values in jsf:
<h:outputText value="#{enum[l:xlate(order.transferStatus)]}" />
Well, enum is just another class. There is nothing stopping you from adding parsing and to-string conversion methods that will parse and output locale-sensitive messages.
Maybe it violates Single Responsible Principle (does it?), but I believe making enum responsible for parsing and returning locale-aware values is the right thing to do.
Just add two methods like this:
public String toString(FacesContext context) {
// need to modify the method
FacesUtil.getMessageValue(context, name);
}
public OrderStatus parse(FacesContext context, String theName) {
for (OrderStatus value : values()) {
if (value.toString(context).equals(theName) {
return value;
}
}
// think of something better
return null;
}
I hope I got the code right, as I am not checking it with IDE now... Is this what you were looking for?
I calculate the message key in the enum like as shown below; so no need to maintain the keys with additional attributes on the enum
public String getMessageKey() {
return String.format("enum_%s_%s", this.getClass().getSimpleName(),
this.name());
}
Then I use it like this
<p:selectOneMenu id="type"
value="#{xyzBean.type}" required="true">
<f:selectItems
value="#{xyzBean.possibleTypes}"
var="type" itemLabel="#{msg[type.messageKey]}">
</f:selectItems>
</p:selectOneMenu>
with having configured a org.springframework.context.support.ReloadableResourceBundleMessageSource in the app context
<bean id="msg"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="/resources/locale/messages" />
<property name="useCodeAsDefaultMessage" value="true" />
<property name="cacheSeconds" value="1" />
</bean>
In case anyone is looking for a simple utility library to handle enum internationalization, please take a look at https://github.com/thiagowolff/litefaces-enum-i18n
The artifact is also available in Maven Central:
<dependency>
<groupId>br.com.litecode</groupId>
<artifactId>litefaces-enum-i18n</artifactId>
<version>1.0.1</version>
</dependency>
Basically, you just need to add the artifact to your project and define the enum respective keys following the described enum naming conventions. The translations (and also CSS class names) can be retrieved using the provided EL functions.