I recently split my project and created a library project and a main project. Having a preferences screen that has custom attributes, i removed the preferences with custom attributes from my preferences.xml, put them into their own xml files, included them back into the preferences.xml file and redefined the individual files in the main project (the process is detailed in the answer to another question here.
The project build and run properly. However, I am getting a RuntimeException whenever i try to open the preferences screen. Removing the prefs with custom attrs fixes the problem, so i have traced it back to there. Unfortunately there is no useful information in the exception.
attrs.xml (exists in lib project)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="numberpickerPref">
<attr name="maxValue" format="integer" />
<attr name="minValue" format="integer" />
</declare-styleable>
</resources>
preferences.xml (also in lib project)
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="#string/pref_VibrationSettingsTitle">
<CheckBoxPreference android:key="#string/pref_vibrateFlagKey"
android:title="#string/pref_VibrateTitle"
android:summary="#string/pref_VibrateSummary"
android:defaultValue="false" />
<include layout="#layout/pref_vibrate_on" />
<include layout="#layout/pref_vibrate_off" />
</PreferenceCategory>
</PreferenceScreen>
pref_vibrate_off.xml (defined in both lib and main projects) (only diff is the my namespace, one points to the lib, the other the main project)
<?xml version="1.0" encoding="utf-8"?>
<!-- Stupid workaround because Android still has a bug where custom attributes in a library cause the executable project
problems when building:
https://stackoverflow.com/questions/4461407/help-with-a-custom-view-attributes-inside-a-android-library-project -->
<com.me.numberpicker.NumberPickerPreference
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:my="http://schemas.android.com/apk/res/com.me.myapp.lib"
android:key="#string/pref_vibrateOffPeriodKey"
android:title="#string/pref_VibrateOffTitle"
android:summary="#string/pref_VibrateOffSummary"
my:maxValue="#string/MaxVibratorOffPeriodInS"
my:minValue="#string/MinVibratorOffPeriodInS"
android:defaultValue="#string/DefaultVibratorOffPeriodInS" />
MyPreferencesActivity.java
public class MegalarmPreferencesActivity extends PreferenceActivity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
All the strings are properly defined in the lib project.
If i'm missing anything, let me know please. The preferences were working fine until i split up my project into a lib and main.
Many thanks!
Sean
PreferenceActivity.onCreate can throw RuntimeExceptions internally that the IDE might catch (if configured to do so), but they are also caught internally. For instance, a missing layout_width tag in the default theme seems to cause an exception.
If the RuntimeException is not percolating back to your code don't worry about it. If it is, could you update your question to include the exception message and stack trace?
Related
I am trying to create a binding for a library, Firebase.Messaging since the current one on Nuget is not up to date, but one class out of this .aar library is not being added to the binding.
This is the RemoteMessage.class.
When I decompile the firebase-messaging.aar I do see the RemoteMessage.class present in the .aar file but when I add this .aar file to my bindingproject and run I get following error:
Warning BG8604: top ancestor RemoteMessage not found for nested type Firebase.Messaging.RemoteMessage.Builder. (BG8604)
This means that for instance the method
public override void OnMessageReceived(RemoteMessage message)
will not be added to my binding because RemoteMessage is not found. I have tried to manually add this to my binding by using <add-note ... but no luck so far.
In my binding I have added references to firebase-common, firebase-iid, googleplayservices-basement, googleplayservices-tasks.
Does anyone have an idea how I can force my binding to recognise the RemoteMessage class and add this to the binding?
Edit:
What I do is create a new Xamarin Binding project for android, add the aar file to the Jars folder & update the Metadata.xml
This is the metadata.xml I am currently using:
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<!-- Rename Namespaces -->
<attr path="/api/package[#name='com.google.firebase.messaging']" name="managedName">Firebase.Messaging</attr>
<!-- Remove *zz* obfuscated classes, interfaces, methods, etc. -->
<remove-node path="/api/package/class[contains(#name, 'zz')]" />
<remove-node path="/api/package/interface[contains(#name, 'zz')]" />
<remove-node path="/api/*/*/method[contains(#name, 'zz')]" />
<remove-node path="/api/*/*/field[contains(#name, 'zz')]" />
<!-- Fix params for some inherited parcelable types -->
<attr path="/api/*/*/method[#name='createFromParcel']/parameter[#name='p0']" name="managedName">source</attr>
<attr path="/api/*/*/method[#name='newArray']/parameter[#name='p0']" name="managedName">size</attr>
<attr path="/api/*/*/method[#name='writeToParcel']/parameter[#name='p0']" name="managedName">dest</attr>
<attr path="/api/*/*/method[#name='writeToParcel']/parameter[#name='p1']" name="managedName">flags</attr>
</metadata>
Nothing in the additions folder, nor the EnumFields or EnumMethods, currently I am using the firebase-messaging-11.8.0.aar for this binding.
After the Binding this is the result I see in the Assembly Browser:
I have figured out why RemoteMessage could not be bound and thus for several methods & classes the top ancestor could not be found.
The GooglePlay Basement & Tasks libraries have changed. This caused an internal problem because the obfuscated class RemoteMessage relies on was now invisible once more, the metadata I was using relied on 11.4.2 but since 11.8.0 this obfuscated class is not found in the Tasks library anymore but in the Basement library, also under a different name.
I have added
<attr path="/api/package[#name='com.google.android.gms.internal']/class[#name='zzbfm']" name="obfuscated">false</attr>
<!-- Fix plural name - legacy compatibility -->
<attr path="/api/package[#name='com.google.android.gms.common.api']/class[#name='Status']" name="managedName">Statuses</attr>
<attr path="/api/package[#name='com.google.android.gms.common.api']/class[#name='Status']" name="extends">Java.Lang.Object</attr>
<add-node path="/api/package[#name='com.google.android.gms.common.api']/class[#name='Status']">
<method abstract="false" deprecated="not deprecated" final="true" name="describeContents" native="false" return="int" static="false" synchronized="false" visibility="public"></method>
</add-node>
To the Metadata.xml, zzbfm is the class RemoteMessage relies on & thus is the one that needs to be unobfuscated.
After updating this in my Basement Metadata.xml & rebinding the Firebase.Messaging library RemoteMessage is now properly bound in the library and accessible.
I'm trying to create a custom attribute that behaves like tools:context, that is with
Android Studio auto complete functionallity
Project classname reference
Support for auto refactory in case I change my class directory
This is my resources.xml
<declare-styleable name="RecyclerView">
<attr name="adapter" format="string"></attr>
</declare-styleable>
This is the usage
<example.com.br.appname.RecyclerView
android:id="#+id/accounts"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="8dp"
app:adapter="example.com.br.appname.AccountAdapter" >
</example.com.br.appname.RecyclerView>
I've tried to use the format reference but it didn't compile as well.
Error:(17, 22) String types not allowed (at 'adapter' with value 'example.com.br.appname.AccountAdapter').
I don’t think this is possible currently. Other similar custom attrs I can think of, for instance app:layout_behavior from the design library, or simply app:layoutManager from RecyclerView all require the full classname, with none of your requirements.
It might be better to store these in a strings resource file, and remember to check it when refactoring class names.
You can consider filing a feature request, since Android Studio has this functionality in special cases (tools:context, class in <view> and <fragment> tags, classes in Manifest...), but I doubt they would add a new attribute format just for this.
so...
apparently, YOU CAN!
Google does this too.
Android Studio understands that the class is being referenced from XML
i.e.
Refactor > Rename works
Find Usages works
and so on...
don't specify a format attribute in .../src/main/res/values/attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyCustomView">
....
<attr name="give_me_a_class"/>
....
</declare-styleable>
</resources>
use it in some layout file .../src/main/res/layout/activity__main_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<SomeLayout
xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- make sure to use $ dollar signs for nested classes -->
<MyCustomView
app:give_me_a_class="class.type.name.Outer$Nested/>
<MyCustomView
app:give_me_a_class="class.type.name.AnotherClass/>
</SomeLayout>
parse the class in your view initialization code .../src/main/java/.../MyCustomView.kt
class MyCustomView(
context:Context,
attrs:AttributeSet)
:View(context,attrs)
{
// parse XML attributes
....
private val giveMeAClass:SomeCustomInterface
init
{
context.theme.obtainStyledAttributes(attrs,R.styleable.ColorPreference,0,0).apply()
{
try
{
// very important to use the class loader from the passed-in context
giveMeAClass = context::class.java.classLoader!!
.loadClass(getString(R.styleable.MyCustomView_give_me_a_class))
.newInstance() // instantiate using 0-args constructor
.let {it as SomeCustomInterface}
}
finally
{
recycle()
}
}
}
I'd like to implement MvxRecyclerView, but I get following exception during runtime in SetContentView():
System.NotSupportedException: Could not activate JNI Handle 0x32700041
(key_handle 0xb29d17e8) of Java type
'mvvmcross/droid/support/v7/recyclerview/MvxRecyclerView' as managed
type 'MvvmCross.Droid.Support.V7.RecyclerView.MvxRecyclerView'.
I use the latest NuGet packages of Xamarin.Android.Support.. (23.3.0) and MvvmCross (4.1.6 / 4.1.7).
Any idea what causes this exception?
More information now on the issue from Ken Kosmowski:
https://github.com/MvvmCross/MvvmCross-AndroidSupport/issues/252
Use the workaround by #kjeremy referenced there, till the issue got fixed:
"The workaround consists of adding Resources\values\attrs.xml file to your Droid project with the following content:"
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<declare-styleable name="MvxRecyclerView">
<attr name="MvxItemTemplateSelector" format="string" />
</declare-styleable>
</resources>
For completion purpose.
With MVVMCross 4.2.0
You should remove the attrs.xml and change all of your MvxItemTemplateSelector references to MvxTemplateSelector.
As with many I am writing my first app. I am trying to use the three button toggle from here: http://androidasilearnit.wordpress.com/2011/03/05/custom-toggle-button/
The only problem I have at the moment is I have created the attrs.xml file and it is in the res/values folder. However, when I have created the TriToggleButton.java class I am getting errors on all three states that are declared in attrs.xml
//Get the attributes created in attrs.xml
private static final int[] STATE_ONE_SET =
{
R.attr.state_one
};
private static final int[] STATE_TWO_SET =
{
R.attr.state_two
};
private static final int[] STATE_THREE_SET =
{
R.attr.state_three
};
I have looked in R.java (as that was a suggested fix) and they are not in there. I can see all the other XML info in there but not the attr
Any ideas?
Edit:
Here is the attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CustomButtonState">
<!-- Use one for every state you want to have -->
<attr name="litres" format="boolean" />
<attr name="usgal" format="boolean" />
<attr name="impgal" format="boolean" />
</declare-styleable>
</resources>
Oh and the clean has really broken it. Now all my resources are not being found!! IN MainActivity.java I am now getting "R cannot be resolved to a variable"
For those in the future. Whenever I have this problem it is invariably an XML problem. For me, it is generally always the menu. As far as i can tell it is an eclipse problem because I can delete the whole XML and the R.java will update. I can post the whole XML back in unchanged and the program will compile and run without problem. It is tedious but I can work around it.
I'm experimenting with my first "Hello World"-like application in Android Studio. I've tried to add a new activity (first via New -> Android Component, didn't like the result, deleted it, then via New -> Activity -> selected Fullscreen activity). Now I get these errors:
Gradle: Execution failed for task ':LanguagesMemorizer:processDebugResources'.
> Could not call IncrementalTask.taskAction() on task ':LanguagesMemorizer:processDebugResources'
C:\...\src\main\res\values\attrs.xml
Gradle: Attribute "buttonBarStyle" has already been defined
Gradle: Attribute "buttonBarButtonStyle" has already been defined
I've tried searching for buttonBarStyle in my project. It was found in:
build folder (I guess I should ignore that, shouldn't I?)
layout file for a new activity (style="?buttonBarStyle")
values\attrs.xml itself (<declare-styleable ...> <attr name="buttonBarStyle" format="reference" /> ...)
values\styles.xml (<style...>... <item name="buttonBarStyle">#style/ButtonBar</item>...)
values-v11\styles.xml (<style...>...<item name="buttonBarStyle">?android:attr/buttonBarStyle</item>...)
All of it was auto-generated. How should I fix this error?
UPDATE: There is a comment in attrs.xml which says
<!-- Declare custom theme attributes that allow changing which styles are
used for button bars depending on the API level.
?android:attr/buttonBarStyle is new as of API 11 so this is
necessary to support previous API levels. -->
So it seems like these attributes are needed for old Androids, but so I guess there is some sort of a conflict between API 11-declared attributes and these manual attributes. How should I fix them?
This is because com.android.support:appcompat-v7:18.0.0 already has this attribute. So if you plan to use this support library (and you should) it is safe to just delete declaration of this attributes from your project \src\main\res\values\attrs.xml. I guess, this duplication is because AndroidStudio new activity wizard, doesn't suppose that you can use support library so it generates all code by itself.