use custom view from library project in my case - android

I have made an Android main library project, in which I have created a custom view class:
package com.my.android.library.layout;
public class CustomView extends View {
...
I also defined styleable for my CustomView:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CustomView">
<attr name="title_text" format="string" />
</declare-styleable>
</resources>
Since I don't want to share my source code to others who are using my library project, so I created an distributed library project, in which I added the jar of above main library project to libs/ folder of distributed library project and copied all resource from main library project to distributed library project.
NEXT, I have made an android app project which uses the distributed library project. In the main layout file of app project, I defined the following :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.my.android.library.layout.CustomView
custom:title_text = "THIS IS TITLE"
/>
<RelativeLayout>
When I run my app, I got the following exception:
E/AndroidRuntime(30993): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.my.android.app/com.my.android.app.MainActivity}: android.view.InflateException: Binary XML file line #7: Error inflating class com.my.android.library.layout.CustomView
E/AndroidRuntime(30993): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2071)
E/AndroidRuntime(30993): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2096)
...
Caused by: java.lang.ClassNotFoundException: com.my.android.library.layout.CustomView
E/AndroidRuntime( 2947): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)
E/AndroidRuntime( 2947): at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
E/AndroidRuntime( 2947): at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
E/AndroidRuntime( 2947): at android.view.LayoutInflater.createView(LayoutInflater.java:552)
E/AndroidRuntime( 2947): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:687)
It seems it can not inflate the my CustomView in layout xml. Why? How to get rid of it?
(I checked the main library jar file, there is CustomView class. Please don't just throw me a link of Android website without explanation.)

Since you are adding the View from a jar, you should be able to specify the namespace as:
xmlns:custom="http://schemas.android.com/apk/lib/root_package_name
Where "root_package_name" could be "com.my.android.library.layout" or "com.my.android.library" or something like that.
If that doesn't work, then it's probably and "Order and Export" problem or the way you are adding the library. Make sure the library is included properly:
Android Activity ClassNotFoundException - tried everything
And finally, if that also fails, then you might need to update Android SDK:
ClassNotFoundException: Didn't find class "com.google.android.gms.ads.AdView"

Let's try do it this way:
public CustomView(Context context) {
this(context, null, 0);
}
public CustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
//init your stuff here
}
Could you give us full stacktrace of the exception ?

Related

Missing resources for Android CardView library

I'm using CardView in my project and I'm getting an error on older devices:
E android.view.InflateException: Binary XML file line #25: Error inflating class android.support.v7.widget.CardView
E at android.view.LayoutInflater.createView(LayoutInflater.java:518)
E at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:570)
E at android.view.LayoutInflater.rInflate(LayoutInflater.java:623)
E at android.view.LayoutInflater.rInflate(LayoutInflater.java:626)
E at android.view.LayoutInflater.inflate(LayoutInflater.java:408)
E at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
Seems similar to a few questions on SO such as this one
My problem is that the solution for that questions feels very hacky and that's understandable as the answer was given last year when Lollipop just entered the public preview. Have things changed since? How do I get the resources?
I've tried a few things such as importing .aar as a module but nothing seems to work. I've followed the official documentation on how to add support libraries (https://developer.android.com/tools/support-library/setup.html#libs-with-res) but that didn't work. Also according to that link - there doesn't seem to be any difference between adding libraries with and without resources for Android Studio?
My app build.gradle includes the following dependencies:
compile 'com.android.support:appcompat-v7:21.0.3'
compile 'com.android.support:cardview-v7:21.0.3'
compile 'com.android.support:recyclerview-v7:21.0.3'
CardView layout is used here
<android.support.v7.widget.CardView
xmlns:card="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?android:attr/selectableItemBackground"
card:cardCornerRadius="6dp"
card:cardUseCompatPadding="true"
tools:ignore="NewApi">
EDIT: the problem noticed on Samsung S2 2.3 - API 19+ works fine
?android:attr/selectableItemBackground is platform related, use it without android: prefix to refer to AppCompat's attribute.

Way to avoid layout file naming conflict among multiple Android projects

Currently, I have an Android project, consists of 1 main project, and multiple library projects.
Just that recently, I realize that if there is same layout filename among main project and library project, bad thing can happen.
third-party-library-project
- res
- layout
- actionbar_custom_view_done_discard.xml
main-project
- res
- layout
- actionbar_custom_view_done_discard.xml
So, if in third-party-library-project, if you are having line of code in its activity,
final View customActionBarView = inflater.inflate(
R.layout.actionbar_custom_view_done_discard, null);
Error stack trace caused by layout file naming conflict
FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{org.yccheok.jstock.gui/group.pals.android.lib.ui.lockpattern.LockPatternActivity}: android.view.InflateException: Binary XML file line #24: Error inflating class <unknown>
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.view.InflateException: Binary XML file line #24: Error inflating class <unknown>
at android.view.LayoutInflater.createView(LayoutInflater.java:613)
at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
at android.view.LayoutInflater.onCreateView(LayoutInflater.java:660)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:685)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
at android.view.LayoutInflater.parseInclude(LayoutInflater.java:830)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:736)
at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
at group.pals.android.lib.ui.lockpattern.LockPatternActivity.initActionBar(LockPatternActivity.java:356)
at group.pals.android.lib.ui.lockpattern.LockPatternActivity.onCreate(LockPatternActivity.java:347)
at android.app.Activity.performCreate(Activity.java:5008)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
... 11 more
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.constructNative(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
at android.view.LayoutInflater.createView(LayoutInflater.java:587)
... 25 more
Caused by: android.content.res.Resources$NotFoundException: Resource is not a Drawable (color or path): TypedValue{t=0x2/d=0x7f010137 a=-1}
at android.content.res.Resources.loadDrawable(Resources.java:1892)
at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
at android.widget.TextView.<init>(TextView.java:614)
at android.widget.TextView.<init>(TextView.java:442)
... 28 more
If I change the layout XML file in third-party-library-project to actionbar_custom_view_done_discard1.xml, the runtime error will gone.
This is not an issues, if the number of library projects is small. Conflict can be solved easily with simple renaming. However, when comes across huge number of library projects, what is a robust way, or strategy to overcome this problem?
Library projects need to ensure that their resource names will be distinctive and not collide with other library projects, such as by applying a prefix to those resource names.
Note that apparently the new Gradle-based build system supports resource subdirectories. I have not yet experimented with this, but if the subdirectory names form part of the resource ID, then putting your resources in a distinctive subdirectory would help to keep the resource IDs distinct (at least for non-values resources).
First I would suggest renaming your project resource file and not the 3rd party file in your first example since you may want to pull changes from the 3rd party library project again. Secondly I would suggest not using too many 3rd party library projects to begin with. From my experience the Android build system still has lots of hiccups with library projects. Things like BuildConfig.DEBUG do not work and I've had issues with library projects that contain jar file dependencies breaking the ability to run unit tests through Android instrumentation. There are tons of other bugs as well, most of them probably fairly obscure but enough of an issue that I don't suggest using library projects any more than absolutely necessary.

Custom Layout Inflation with Fragments in Robolectric not working

When inflating a layout in a Fragment, with the LayoutInflater, i am getting this exception:
./res/layout/locations_list.xml line #-1 (sorry, not yet implemented): Error inflating class com.costum.android.widget.LoadMoreListView
I figured out that this is happening when inflating a custom layout in
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.locations_list, container, false);
}
Edit This is the locations_list.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:orientation="vertical" >
<com.costum.android.widget.LoadMoreListView
android:id="#+id/android:list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="0dp" />
</LinearLayout>
any other layout inflator works, like in this test:
#Test
public void testInflator() {
ActivityController<SherlockFragmentActivity> activityController = CustomTestRunner
.startActivity();
SherlockFragmentActivity activity = activityController.get();
LayoutInflater from = LayoutInflater.from(activity);
View view = from
.inflate(com.twisper.R.layout.locations_list_item, null);
assertNotNull(view);
}
I am using Robolectric with the 2.2-SNAPSHOTs , Now my question is how could I work around this issue or how could I implement the missing functionality, the robolectric documentation is very sparse, hence I had trouble to find any starting point.
Full Stack Trace
android.view.InflateException: XML file ./res/layout/locations_list.xml line #-1 (sorry, not yet implemented): Error inflating class com.costum.android.widget.LoadMoreListView
at android.view.LayoutInflater.createView(LayoutInflater.java:613)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:687)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
...
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at android.view.LayoutInflater.$$robo$$LayoutInflater_1d1f_createView(LayoutInflater.java:587)
at android.view.LayoutInflater.createView(LayoutInflater.java)
at android.view.LayoutInflater.$$robo$$LayoutInflater_1d1f_createViewFromTag(LayoutInflater.java:687)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java)
at android.view.LayoutInflater.$$robo$$LayoutInflater_1d1f_rInflate(LayoutInflater.java:746)
at android.view.LayoutInflater.rInflate(LayoutInflater.java)
at android.view.LayoutInflater.$$robo$$LayoutInflater_1d1f_inflate(LayoutInflater.java:489)
at android.view.LayoutInflater.inflate(LayoutInflater.java)
at android.view.LayoutInflater.$$robo$$LayoutInflater_1d1f_inflate(LayoutInflater.java:396)
at android.view.LayoutInflater.inflate(LayoutInflater.java)
...
Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: -9
at java.lang.String.substring(String.java:1911)
at org.robolectric.res.ResName.qualifyResName(ResName.java:50)
at org.robolectric.res.Attribute.getResourceReference(Attribute.java:138)
at org.robolectric.res.Attribute.qualifiedValue(Attribute.java:127)
at org.robolectric.res.builder.XmlFileBuilder$XmlResourceParserImpl.qualify(XmlFileBuilder.java:316)
at org.robolectric.res.builder.XmlFileBuilder$XmlResourceParserImpl.getAttributeValue(XmlFileBuilder.java:340)
at org.robolectric.shadows.ShadowResources.findAttributeValue(ShadowResources.java:252)
at org.robolectric.shadows.ShadowResources.attrsToTypedArray(ShadowResources.java:188)
at org.robolectric.shadows.ShadowResources.access$000(ShadowResources.java:51)
at org.robolectric.shadows.ShadowResources$ShadowTheme.obtainStyledAttributes(ShadowResources.java:460)
I also posted the issue on robolectrics issue tracker.
I figured it out, and if you got stock to such an situation just look for your IDs in the XML, even though
android:id="#+id/android:list"
is often seen in some example code it must be:
android:id="#android:id/list"
The last version of Robolectric (3.0-Snapshot) has some problems with customized views.
To fix that, do the follow:
In the module app where your code is, create a file called project.properties, at the same level as AndroidManifest.xml
Fill the content with reference to the class folder of build. e.g. for StaggeredGridView:
android.library.reference.1=../../build/intermediates/exploded-aar/com.etsy.android.grid/library/1.0.5
Here you must check three things:
There should be one line per reference
Each reference has one number (1, 2, 3), which should be increase by one each time
The version number folder at the end must match with the version number in your build.gradle file.
You have an example of project working here:
https://github.com/jiahaoliuliu/RobolectricSample/blob/master/app/src/main/project.properties
In my case I got this problem when I had this in my app:
<dependency>
<groupId>com.google.android</groupId>
<artifactId>support-v4</artifactId>
<version>r13</version>
</dependency>
but this in my unittest project:
<dependency>
<groupId>com.google.android</groupId>
<artifactId>support-v4</artifactId>
<version>r7</version>
</dependency>
The older version of the support library I used in the tests didn't contain the class I was trying to use (android.support.v4.widget.DrawerLayout).
In my case, my FragmentActivity XML was inflating a Fragment that was expecting a Bundle. I swapped the XML for a FrameLayout holder and added the fragment with the proper bundle in the activity.

Android - Resources$NotFoundException

I have an App with over 100.000 Users. But on some devices (~50) I get a strange exception. The stack traces says, that there is an drawable not found.
Here is the stack trace:
java.lang.RuntimeException: Unable to start activity ComponentInfo{mindmApp.the.big.bang.theory.quiz/mindmApp.the.big.bang.theory.quiz.GameNormalActivity}: android.view.InflateException: Binary XML file line #237: Error inflating class
...
Caused by: android.view.InflateException: Binary XML file line #237: Error inflating class
at android.view.LayoutInflater.createView(LayoutInflater.java:606)
at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
at android.view.LayoutInflater.onCreateView(LayoutInflater.java:653)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:678)
...
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.constructNative(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
at android.view.LayoutInflater.createView(LayoutInflater.java:586)
... 28 more
Caused by: android.content.res.Resources$NotFoundException: File res/drawable/textviewxml_joker.xml from drawable resource ID #0x7f02003d
at android.content.res.Resources.loadDrawable(Resources.java:1956)
at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
at android.view.View.(View.java:2841)
at android.widget.TextView.(TextView.java:580)
at android.widget.TextView.(TextView.java:573)
I have no idea why this drawable (it's a xml-file) is not found.
The binary XML file line #237 is:
<TextView
android:id="#+id/textViewSkip"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_weight="1"
android:background="#drawable/textviewxml_joker"
android:gravity="center"
android:text="#string/tvSkip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#color/color_textview"
android:textSize="22sp" />
And here is the textviewxml_joker.xml file:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="#drawable/textview_joker_pressed"
android:state_pressed="true"/>
<item android:drawable="#drawable/textview_joker"/>
</selector>
Have anybody an idea t osolve this problem?
Best Regards!
If your textviewxml_joker.xml file isn't in drawable, but rather in a drawable-* folder, then those few devices that get the error may not meet the conditions to use the drawable-* folder.
Put it in drawable as well and it should fix it.
This could also happen if the resource you are referring to (lets call it ResA) is in-turn referring to a resource which is missing (lets call it ResB).
Android will raise the ResourceNotFoundException for ResA even though whats really missing is ResB. Such is life!
In my case, ResB was defined in the values-swxxxdp but not in values. Hence I was getting this exception on phones but not on tablets.
If you have multiple resource folders, make sure that Android finds your drawable xml for every possible qualifier combination (Providing Resources). Looking at the device types that have this error might give you a hint where to look.

android custom component to layout

I would like to add my custom ImageView to the xml layout.
main.xml :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.android.gag.TouchImageView
android:id="#+id/Image1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:clickable="true"
android:scaleType="center" />
<ImageButton
android:id="#+id/imageButton1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" />
</RelativeLayout>
TouchImageView, as its name implies, extends the ImageView class.
Main.java
touchImageView = (TouchImageView)findViewById(R.id.Image1);
My app crashes. Logcat output:
10-16 20:38:20.275: E/AndroidRuntime(11354): FATAL EXCEPTION: main
10-16 20:38:20.275: E/AndroidRuntime(11354): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.android.gag/com.android.gag.Main}: android.view.InflateException: Binary XML file line #6: Error inflating class com.android.gag.TouchImageView
10-16 20:38:20.275: E/AndroidRuntime(11354): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1970)
idRuntime(11354): Caused by: android.view.InflateException: Binary XML file line #6: Error inflating class com.android.gag.TouchImageView
10-16 20:38:20.275: E/AndroidRuntime(11354): at android.view.LayoutInflater.createView(LayoutInflater.java:589)
10-16 20:38:20.275: E/AndroidRuntime(11354): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:680)
Please, could anyone help me?
I am a beginner, so answers like '' replace "class library" with "Android library project"'' are pointless because they are too vague and I don't know where to start and where to go.
EDIT: Link to my TouchImageView class
The code for your custom View class is missing two constructors. From the Android docs for the View class:
View(Context context, AttributeSet attrs)
Constructor that is called when inflating a view from XML.
View(Context context, AttributeSet attrs, int defStyle)
Perform inflation from XML and apply a class-specific base style.
It's crashing because it can't find the constructor it needs, so it can't inflate the view.
Implement both of these constructors for your TouchImageView class and see if the problem goes away.

Categories

Resources