AIDL interface can't find import for Parcelable class - java

My issue seems to be similar to this question and this one but it is a bit different.
I am making an AIDL service that is in a Library project and using it in my application. I have a class Vehicle that is in my application that I have made parcelable so that I can use it in my interface. (I would like to get a List of vehicles from my service that is in the library to my application)
Do I need a Vehicle.java in both the application and the library?
Do I need a Vehicle.aidl in both?
I had Vehicle.java AND Vehicle.aidl in both application and library and I began running into a problem in my application that when I called a method from my interface eclipse wanted me to define it as the Vehicle of the library class and not the application(although they are the same and both parcelable).
public List<Vehicle> getVehicles(){...code... }
In an effort to resolve this, I tried to make it the application's vehicle class rather than the library's vehicle class in my IRemoteInterface.aidl(in the listed variation below, i get an error that it can't find the import. In other variations like having it be List and no import, it says unknown return type).
package LIBRARY;
import LIBRARY.RelPoint;
import LIBRARY.IRemoteServiceCallback;
import LIBRARY.FleetStatus;
import APPLICATION.Vehicle;
interface IRemoteInterface {
int getPid();
void registerCallback(IRemoteServiceCallback callback);
void unregisterCallback(IRemoteServiceCallback callback);
List<Vehicle> getVehicles();
}
Here is my parcelable Vehicle class from the application :
package APPLICATION;
import java.util.Date;
import android.os.Parcel;
import android.os.Parcelable;
public class Vehicle implements Parcelable {
public static final String TAG = "Vehicle";
long vehicleID;
long trackID;
String vehicleName;
public static final Parcelable.Creator<Vehicle> CREATOR = new Parcelable.Creator<Vehicle>() {
public Vehicle createFromParcel(Parcel src) {
return new Vehicle(src);
}
public Vehicle[] newArray(int size) {
return new Vehicle[size];
}
};
public Vehicle(Parcel src) {
readFromParcel(src);
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(vehicleID);
dest.writeLong(trackID);
dest.writeString(vehicleName);
}
public void readFromParcel(Parcel src) {
vehicleID = src.readLong();
trackID = src.readLong();
vehicleName = src.readString();
}
public int describeContents() {
// nothing special
return 0;
}
public Vehicle() {
}
//getter and setter methods below that I removed
}

I'm reasonably certain you need to have the Parcelable classes in the same package on both ends (which is what you end up with by using the one from APPLICATION on the library side, I would just do it the other way around). This package has to also be the one declared in the corresponding aidl file.
I'd suggest to use a subpackage like com.example.interop to make this cleaner (i.e., separate the shared objects in their own package). Both sides should then have a Java file in that package + an aidl file that declares it.

I had the same issue and got it working with the following folder and file structure:
Under src/main create a directory named "aidl". This is where Android by default looks for .aidl files
Under "aidl/" create a directory "com/mypackage/util"
Then under "src/main/aidl/com/mypackage/util" put the .aidl file of your service and a separate .aidl file of your Parcelable. If the service is called IGetCards then the aidl file must be named IGetCards.aidl and if you Parcelable is called Cards then it must be in its own file named Cards.aidl.
In src/main/aidl/com/mypackage/util/IGetCards.aidl:
package com.mypackage.util;
import com.mypackage.util.Cards;
/** Example service interface */
interface IGetCards {
/** Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
Cards getCards();
}
In src/main/aidl/com/mypackage/util/Cards.aidl:
package com.mypackage.util;
parcelable Cards;
Check each file has a package statement at the top and that the service file IGetCards has an import statement at the top importing the Cards class.
Now in the Java directory src/main/java/com/mypackage/util, put a corresponding Cards.kt file which implements the interface. Make sure Cards.kt has a package statement at the top that matches Cards.aidl.
In src/main/java/com/mypackage/util/Cards.kt:
package com.mypackage.util;
class Cards() : Parcelable {
//implement members
...
}

Related

When I have an enum defined in the same source file as the class that uses it, why is an import of the enum needed?

If a source file defining a class also defines an enum used by the class (and users of the class), why does the source file require an import of that enum? I am using Netbeans 8.2 by the way.
Here is a simple example:
// file and class name Foo, enum name Bar
package pak;
import pak.Foo.Bar; // <-- why is this required?
public class Foo {
public static enum Bar { ZOT,BIF };
public Foo() {}
public void doFooBar(Bar op) { /* whatever */ }
}
Referring to the simple example above, the Netbeans compiler insists I include the import of the enum.
Why do I need to import when the enum is in the same source file as the class?

User defined class import at run time

I'm trying to figure out how to resolve the following use case:
A user can define a Java class, say MyFoo like this (the code is generated automatically and the guid is set to avoid name collisions)
import com.bar.entities.BaseEntity;
package com.bar.entities.defined.79B35635_DEDF_A344_9621_0477A6E71725;
public class MyFoo extends BaseEntity {
public String getFoo() { ... }
public Integer getBar() { ... }
#Override
public byte[] serialize() {...}
}
A user can import that Java class in other class like this:
package com.bar.business;
import com.bar.entities.defined.79B35635_DEDF_A344_9621_0477A6E71725.MyFoo;
public class Business extends Minion {
#Override
public void execute(EntityProvider ep) {
MyFoo myFoo = ep.get("myFoo", MyFoo.class);
if (myFoo.getBar() < 10) {
notifyMaster();
}
}
}
Additionaly I have a Java application (actually a Grizzly HTTP Server with a Jersey API Rest) that must be able to compile both classes.
¿How can I compile both classes? The first one can be compiled. The second one can't because the compiler says that the method getBar() is not known (it does not fail at the import line, surpringsly)
I want to send both Class<?> instances over the network and use them elsewhere via reflection with getDeclaredConstructor()
Kind regards.

override the new package with the old one

Considering a java application with a embedded X impl/jar file, for example com.test package.
and we cannot change and modify the jar file.
Now suppose I have a X1.jar file which is modified version of exist X(com.test) package.
Question:
Is it possible to override the X1.jar implementation with embedded(exist) implementation just before the library gets loaded? and again, assume we cannot change the package anyway.
I'd like that to redirect all the types under com.test package to the new one.
Thanks in advance.
As per m0skit0's suggestion:
Orig class:
package example.x
public class SomeClass
{
public SomeClass(String neededVar)
{...}
public String someMethod(String someVar)
{
// original implementation
}
}
Custom class:
import example.x.SomeClass
public class MySomeClass extends SomeClass
{
public MySomeClass(String neededVar)
{
super(neededVar);
// anything else
}
#Override
public String someMethod(String someVar)
{
// implement differently
super.someMethod(someVar);
// or add to it
}
}

Java : The import collides with another import statement

I have imported an Existing Java Application into my Workspace .
I see that , a class with same name is present in different packages with in the Application.
For example a class named "Status.java" is present with in
com.tata.model.common.Status;
com.bayer.frontlayer.dao.Status;
When I tried to use both of them within a class, for example as shown below
import com.tata.model.common.Status;
import com.bayer.frontlayer.dao.Status;
public class Adapter
{
}
It started giving an error in Eclipse stating
The import com.bayer.frontlayer.dao.Status collides with another import statement
Is there anyway to solve this without changing the name of the classes??
Thank you.
You can use them explicitly without importing them, so the included package name differentiates between the two:
//No imports required!
public class Adapter
{
private com.tata.model.common.Status x;
private com.bayer.frontlayer.dao.Status y;
}
You can import just one of the classes and use the fully qualified name for the other one.
e.g.
import com.tata.model.common.Status;
//import com.bayer.frontlayer.dao.Status;
class SomeClass{
void someMethod(){
new Status(); // com.tata.model.common.Status
new com.bayer.frontlayer.dao.Status(); //com.bayer.frontlayer.dao.Status
}
}
Though I think it would be less confusing in your case if you just used the fully-qualified names for both classes.
Directly apply full Class Names wherever applicable. Eg-
public class SomeClass {
public someMethod() {
com.myapp.someotherpackage.Status = "something";
com.some.other.package.Status = "otherthing";
if(com.myapp.someotherpackage.Status == com.some.other.package.Status) {
}
....
}
}

Is it safe to OSGi export API containing reference to implementation code?

Let's imagine I implement the following:
public enum ExportAPIForOSGi {
;
public static SpecialObject newSpecialObject() {
return new SpecialObjectImplv1();
}
}
public abstract class SpecialObject {
public abstract String specialMethod(String s);
}
public class SpecialObjectImplv1 extends SpecialObject {
#Override
public String specialMethod(String s) {
return "33" + s;
}
}
Each class is declared in its own separate file. Only ExportAPIForOSGi and SpecialObject are to be OSGi exported.
My question: is it safe to export ExportAPIForOSGi since it contains an explicit reference to implementation code (i.e., SpecialObjectImplv1)? Is the implementation code going to be exposed?
Let's imagine that later, I use SpecialObjectImplv2 in ExportAPIForOSGi instead of v1? Is this going to be an issue?
You need to export the package(s) containing ExportAPIForOSGi and SpecialObject since they are your public API. SpecialObjectImplv1 should be in another package which is not exported. You are then free to change the implementation of newSpecialObject to use another impl class since the impl class is not visible in the signature of the public API.

Categories