0

I have a java class which uses JobIntentService in Android (package name : import android.support.v4.app.JobIntentService;. This class is used in the .aar file that I have binded in my Xamarin project.

I created an Application which uses the .aar file for certain methods available there.

The Building operation works fine.

But the problem happen when I'm running the application, it throws me a

Java.Lang.NoClassDefFoundError has been thrown
Failed resolution of : Lcom/<package_name_of_class>/MyService$Background

I checked the References directory in order to see if the class was there, and the class is really there...

I added the attribute

<attr path="/api/package[@name='com.<package_name_of_class>']/class[@name='MyService.Background']" name="extends">java.lang.Object</attr>

in the Metadata.xml file under the Transforms directory to bind that service.

I know that there is some issues regarding to the connection of that class, but I sincerely don't know to solve it...

What should I do in order to solve this problem ?

EDIT 2

For example, in my .aar file I have this class:

public class MyService{

/**
 * Class which handles Foreground execution behaviour.
 *
 *
 * */
public static class Foreground extends IntentService{
    public Foreground(){super("MyService.Foreground");}

    @Override
    public void onCreate() {
        super.onCreate();
        MyService.onCreate(this.getApplicationContext());
    }

    /**
     * This method is invoked on the worker thread with a request to process.
     * Only one Intent is processed at a time, but the processing happens on a
     * worker thread that runs independently from other application logic.
     * So, if this code takes a long time, it will hold up other requests to
     * the same IntentService, but it will not hold up anything else.
     * When all requests have been handled, the IntentService stops itself,
     * so you should not call {@link #stopSelf}.
     *
     * @param intent The value passed to {@link
     *               Context#startService(Intent)}.
     *               This may be null if the service is being restarted after
     *               its process has gone away; see
     *               {@link Service#onStartCommand}
     *               for details.
     */
    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        MyService.onHandleIntent(this.getApplicationContext(), intent);
    }
}

/**
 * Class which handles Background execution behaviour for android Oreo.
 *
 * */
public static class Background extends JobIntentService{
    private static final String TAG = "MyService.Background";
    protected static final int JOB_ID = 8888;


    /**
     * Convenience method for enqueuing work in to this service.
     */
    public static void enqueueWork(Context context, Intent work) {
        enqueueWork(context, MyService.Background.class, MyService.Background.JOB_ID, work);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        MyService.onCreate(this.getApplicationContext());
    }

    /**
     * Called serially for each work dispatched to and processed by the service.  This
     * method is called on a background thread, so you can do long blocking operations
     * here.  Upon returning, that work will be considered complete and either the next
     * pending work dispatched here or the overall service destroyed now that it has
     * nothing else to do.
     * <p>
     * <p>Be aware that when running as a job, you are limited by the maximum job execution
     * time and any single or total sequential items of work that exceeds that limit will
     * cause the service to be stopped while in progress and later restarted with the
     * last unfinished work.  (There is currently no limit on execution duration when
     * running as a pre-O plain Service.)</p>
     *
     * @param intent The intent describing the work to now be processed.
     */
    @Override
    protected void onHandleWork(@NonNull Intent intent) {
        MyService.onHandleIntent(this.getApplicationContext(), intent);
    }
}

 public static void onCreate(Context mApplicationContext) {
    Apps.init(mApplicationContext);
}

protected static void onHandleIntent(Context mApplicationContext, Intent intent) {
    String action = intent.getAction();
    Bundle extras = intent.getExtras();

    // etc
}
}

And in my Transforms folder, I added that line :

<attr path="/api/package[@name='com.android.internal.service']/class[@name='MyService.Background']" name="extends">mono.android.app.Service</attr>

Note that this class is a JobIntentService, maybe it can be the source of the problem...

But I also tested with that line too :

<attr path="/api/package[@name='com.android.internal.service']/class[@name='MyService.Background']" name="extends">java.lang.Object</attr>

And the problem still continues at runtime

EDIT 3

When I build the project, the api.xml files generate those lines :

<class abstract="false" deprecated="not deprecated" 

extends="java.lang.Object" extends-generic-aware="java.lang.Object" final="false" name="MyService" static="false" visibility="public">
<constructor deprecated="not deprecated" final="false" name="MyService" static="false" type="com.android.internal.service.MyService" visibility="public">
</constructor>
<method abstract="false" deprecated="not deprecated" final="false" name="onCreate" native="false" return="void" static="true" synchronized="false" visibility="public">
<parameter name="p0" type="android.content.Context">
</parameter>
</method>
<method abstract="false" deprecated="not deprecated" final="false" name="onHandleIntent" native="false" return="void" static="true" synchronized="false" visibility="protected">
<parameter name="p0" type="android.content.Context">
</parameter>
<parameter name="p1" type="android.content.Intent">
</parameter>
</method>
</class>
<class abstract="false" deprecated="not deprecated" extends="java.lang.Object" extends-generic-aware="java.lang.Object" final="false" name="MyService.1" static="true" visibility="">
<implements name="java.lang.Runnable" name-generic-aware="java.lang.Runnable">
</implements>
<method abstract="false" deprecated="not deprecated" final="false" name="run" native="false" return="void" static="false" synchronized="false" visibility="public">
</method>
</class>
<class abstract="false" deprecated="not deprecated" extends="java.lang.Object" extends-generic-aware="java.lang.Object" final="false" name="MyService.2" static="true" visibility="">
<implements name="java.lang.Runnable" name-generic-aware="java.lang.Runnable">
</implements>
<method abstract="false" deprecated="not deprecated" final="false" name="run" native="false" return="void" static="false" synchronized="false" visibility="public">
</method>
</class>
<class abstract="false" deprecated="not deprecated" extends="java.lang.Object" extends-generic-aware="java.lang.Object" final="false" name="MyService.3" static="true" visibility="">
<implements name="java.lang.Runnable" name-generic-aware="java.lang.Runnable">
</implements>
<method abstract="false" deprecated="not deprecated" final="false" name="run" native="false" return="void" static="false" synchronized="false" visibility="public">
</method>
</class>
<class abstract="false" deprecated="not deprecated" extends="java.lang.Object" extends-generic-aware="java.lang.Object" final="false" name="MyService.4" static="true" visibility="">
<implements name="java.lang.Runnable" name-generic-aware="java.lang.Runnable">
</implements>
<method abstract="false" deprecated="not deprecated" final="false" name="run" native="false" return="void" static="false" synchronized="false" visibility="public">
</method>
</class>
<class abstract="false" deprecated="not deprecated" extends="java.lang.Object" extends-generic-aware="java.lang.Object" final="false" name="MyService.5" static="true" visibility=""/>

<class abstract="false" deprecated="not deprecated" extends="android.support.v4.app.JobIntentService" extends-generic-aware="android.support.v4.app.JobIntentService" final="false" name="MyService.Background" static="true" visibility="public">
<constructor deprecated="not deprecated" final="false" name="MyService.Background" static="false" type="com.android.internal.service.MyService.Background" visibility="public">
</constructor>
<method abstract="false" deprecated="not deprecated" final="false" name="enqueueWork" native="false" return="void" static="true" synchronized="false" visibility="public">
<parameter name="p0" type="android.content.Context">
</parameter>
<parameter name="p1" type="android.content.Intent">
</parameter>
</method>
<method abstract="false" deprecated="not deprecated" final="false" name="onHandleWork" native="false" return="void" static="false" synchronized="false" visibility="protected">
<parameter name="p0" type="android.content.Intent">
</parameter>
</method>
<field deprecated="not deprecated" final="true" name="JOB_ID" static="true" transient="false" type="int" type-generic-aware="int" value="8888" visibility="protected" volatile="false">
</field>
</class>
<class abstract="false" deprecated="not deprecated" extends="android.app.IntentService" extends-generic-aware="android.app.IntentService" final="false" name="MyService.Foreground" static="true" visibility="public">
<constructor deprecated="not deprecated" final="false" name="MyService.Foreground" static="false" type="com.android.internal.service.MyService.Foreground" visibility="public">
</constructor>
<method abstract="false" deprecated="not deprecated" final="false" name="onHandleIntent" native="false" return="void" static="false" synchronized="false" visibility="protected">
<parameter name="p0" type="android.content.Intent">
</parameter>
</method>
</class>

EDIT 3

enter image description here

Damiii
  • 1,363
  • 4
  • 25
  • 46

2 Answers2

0

Here is a sample of how to declare a metadata file under transforms directory.

<metadata>
    <!--
  This sample removes the class: android.support.v4.content.AsyncTaskLoader.LoadTask:
  <remove-node path="/api/package[@name='android.support.v4.content']/class[@name='AsyncTaskLoader.LoadTask']" />

  This sample removes the method: android.support.v4.content.CursorLoader.loadInBackground:
  <remove-node path="/api/package[@name='android.support.v4.content']/class[@name='CursorLoader']/method[@name='loadInBackground']" />
  -->
    <remove-node path="/api/package[starts-with(@name, 'com.actionbarsherlock.internal')]" />


    <!-- Canonicalize the Java package names -->
    <attr path="/api/package[@name='com.actionbarsherlock']" name="managedName">Xamarin.ActionbarSherlockBinding</attr>
    <attr path="/api/package[@name='com.actionbarsherlock.widget']" name="managedName">Xamarin.ActionbarSherlockBinding.Widget</attr>
    <attr path="/api/package[@name='com.actionbarsherlock.app']" name="managedName">Xamarin.ActionbarSherlockBinding.App</attr>
    <attr path="/api/package[@name='com.actionbarsherlock.view']" name="managedName">Xamarin.ActionbarSherlockBinding.Views</attr>
</metadata>

For full project sample see the link below , https://github.com/xamarin/monodroid-samples/blob/master/ActionBarSherlock/ActionBarSherlock/Transforms/Metadata.xml

krishank Tripathi
  • 616
  • 1
  • 7
  • 23
  • I tested something. Even if I remove the attribute in the `ManifestData`, the project will build but when comes the part of executing the application at runtime, it will still throw the same error – Damiii Mar 23 '18 at 17:59
0

From your description and codes, you are creating a class with dependency of Android.Support.V4 library. If your dependency is missing, binding library will remove the class automatically.

So, what you need to do is to add Xamarin.Android.Support.v4 nuget package to your binding library and it will work fine:

enter image description here

There is no need to edit the metadata.xml files in this case.

Elvis Xia - MSFT
  • 10,801
  • 1
  • 13
  • 24
  • Well the problem is that I have that already :/ I edited my post in order to show the screenshot of that reference. – Damiii Mar 26 '18 at 11:21
  • Could you provide the codes, which consume the class? And also, please enable Diagnostic log to check if we can find anything useful, you can enable that in Visual Studio for Mac by `Visual Studio->Preferences->Projects->Build->Log verbosity(Dropbox)->Diagnostic`. – Elvis Xia - MSFT Mar 27 '18 at 00:30
  • Well, it seems that, I don't know how....., It solves from one day to another ! I didn't change any pieces of code ! So I guess it is solved... Thank you for your time @Elvis – Damiii Mar 28 '18 at 09:24