how to import class of another package from different project in AIDL file? - android

I have a AIDL file that implemented in the package under ProjectA, and I am trying to import a Parcelable class (Foo) from another package under ProjectB. Below is the way how I implemented the MyService.AIDL file:
package com.packageA.projectA
import com.packageB.projectB.Foo
interface MyService{
void getSomething(Foo foo);
}
However, I get this compilation error "couldn't find import for class com.example.projectB.Foo". If I copied the packageB to packageA, then I will get no compilation error.
Is there a way to import parcelable class from package under different project? I know there're multiple questions on stackoverflow and elsewhere (like google group) about importing parcelable under the same project, but none from different projects. Thank you for your time.

You mean to say that you defined the class for the parcelable class and you are not able to use that class in the aidl ?
Try the below solution.
you have your MyService.AIDL in your src/xxx path.
Now create Foo.aidl (name should be same)in the same path and define that Foo.aidl as below.
package com.packageB.projectB
parcelable Foo
now remove the import statement from MyService.AIDL and re-type it (its for refreshing , else it will show same error)
now that import error must be gone.

I know this is old but I had the same problem and found the solution very ugly.
I had two classes defined in the package:
com.lni.codephg.inter
I had another class defined in the package
com.pcha.androidbtmanager
The actual AIDL interfaces were defined in the package
com.pcha.proprietary.handler
The client would be looking for remote services implementing methods in the package com.pcha.proprietary.handler.
So what did my AIDL file hierarchy have to look like to make this work?
src\main\aidl\com\lni\codephg\inter
MetricIntermediary.aidl
MdsIntermediary.aidl
src\main\aidl\com\pcha\androidbtmanager
PhdInformation.aidl
src\main\aidl\com\pcha\proprietary\handler
IConnectionCallback.aidl
IIntermediaryCallback.aidl
IProprietaryDeviceHandler.aidl
IStatusEventCallback.aidl
The 'one-liner' files defining the custom classes like MdsIntermediary.aidl look like this
// MdsIntermediary.aidl
package com.lni.codephg.inter;
parcelable MetricIntermediary;
I have to admit I do understand why these one-liner files must exist in such a weird form.
Then the interface AIDL files that reference them (for example IIntermediaryCallback.aidl) look like this
// IIntermediaryCallback.aidl
package com.pcha.proprietary.handler;
// Declare any non-default types here with import statements
import com.lni.codephg.inter.MdsIntermediary;
import com.lni.codephg.inter.MetricIntermediary;
interface IIntermediaryCallback
{
void onMdsIntermediary(in MdsIntermediary mds);
void onReceiveMetricIntermediaries (in List<MetricIntermediary> metricList, in
MdsIntermediary mds);
}
Of course I had to implement the Parcelable methods on the said custom classes. However, as ugly as that was, Android Studio seemed to do it for me. Since I know nothing about Parcelable I don't know if it is good enough or if I have to do some massaging.
This was painfully difficult. Hope this will save someone hours of frustration.

Related

How to use a class in an imported jar?

What I am doing: Call the method inside the class in a very simple jar from main Activity. (The jar will be used as sdk to make connection with a server but right now is for testing)
Error message
This is all the code in my jar, just 1 class
I have tried this, and changed the class into singleton pattern and this, and make everything in the class public. I also found this one but same error different issue
Create class as public class to make it accessible. In java if you don't provide any access modifier it becomes default.
Refer Java Access Modifiers here
public class Jartest{
//Your Implementation
}
In addition to create the class with public modifier, all classes must be warped inside a package. Otherwise it becomes default package and there is no way to access it beside reflection. In another word, when you create the jar, create the class inside a package and Android studio should be able to import the package and use the class inside the jar.

Package Level Protection in Kotlin [duplicate]

In Java, we have the package protected (default) modifier for classes, which allows us to have many classes in a single package but exposes only a few and keeps the logic encapsulated.
With Kotlin this doesn't seem to be the case. If I want a few classes to be visible to each other but no further, I have to use a private modifier which limits visibility to a single file.
So if you want 10 classes in a package but only one of them to be public, you'd have to have one huge file with all the classes in it (and private all over the place).
Is this normal practice or there is a way to achieve some similar modularity in Kotlin?
I don't understand: if they have the notion of a package, why did they get rid of package protected access?
Update: We might have package protected visibility after all
see the discussion here
Update: If you read through the discussion and still think this is a must-have feature for the language, please vote here
Kotlin, compared to Java, seems to rely on packages model to a lesser degree (e.g. directories structure is not bound to packages). Instead, Kotlin offers internal visibility, which is designed for modular project architecture. Using it, you can encapsulate a part of your code inside a separate module.
So, on top level declarations you can use
private to restrict visibility to the file
internal to restrict visibility to the module
At this point, there is no other option for visibility restriction.
As a workaround for me on android I've created #PackagePrivate annotation and lint checks to control access. Here you can find the project.
Lint checks are obviously not that strict as compiler checks and some setup needed to fail the build on errors. But android studio picks up lint checks automatically and shows error immediately while typing. Unfortunately I don't know a way to exclude annotated members from autocomplete.
Also, as lint is a purely compile-time tool, no checks at runtime performed.
As #hotkeys points out, you can use the internal keyword in a module or you can put all classes that would otherwise belong in a package inside a single file, but sticking several classes in a file may be a questionable design decision.
For me, the package visibility is helpful for its documenting value. I want to know what public interface some package is presenting to the rest of the project, hide factory implementation classes and so on.
So even if it's possible to access package-private classes and methods in Java, I still choose to use the package modifier.
For this I created a project with a single annotation:
package com.mycompany.libraries.kotlinannotations;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
#Documented
#Retention(SOURCE)
#Target({ TYPE, METHOD, CONSTRUCTOR })
/**
* Use in Kotlin code for documentation purposes.
*
* Whenever a Kotlin class or method is intended to be accesible at package level only.
*
*/
public #interface PackagePrivate {
}
Then I can use this annotation in any Kotlin project.
The second step, which I haven't done yet, is creating a PMD rule to enforce this with maven (or any other build tool for that matter) and also be able to see violations of the rule in my IDE with the pmd plugin.
There no is full Kotlin support in pmd at this moment but it seems to be expected at some point.
A near-replacement for package private visibility is available using the opt-in requirements feature (credit to pdvrieze on Kotlin discussions). This is the annotation syntax typically used to flag experimental features in an API.
To use it, create an annotation denoting package private declarations:
#RequiresOptIn(message = "Only to be used in MyPackage")
#Retention(AnnotationRetention.BINARY)
annotation class MyPackagePrivate
Then annotate any methods you want to be package private with it:
#MyPackagePrivate
fun aPackagePrivateMethod() {
// do something private within a package
}
In this way a warning will be generated on any method that calls the annotated method unless the calling method is itself annotated with the corresponding #OptIn annotation, here shown at class level:
#OptIn(MyPackagePrivate::class)
class AClassInThePackage {
fun userOfPackagePrivateMethod() {
aPackagePrivateMethod()
}
}
This, then, produces a similar effect to Java's package private, except that calling methods need to explicitly opt in to using a package private declaration.
If it is desired to generate an error rather than a warning, the level parameter of #RequiresOptIn can be specified:
#RequiresOptIn(level = RequiresOptIn.Level.ERROR, message = "Only to be used in MyPackage")
// annotation declaration as before
Package-based protection is pointless in Kotlin because packages themselves are unprotected
In Java, package was tied to directory structure. So if you put your classes in com\example\yoursecretengine, any attempt (deliberate or accidental) to add a rogue class there would be easily noticeable. This is the kind of security we've depended on.
Kotlin removes the ties between directory and package, so I can put my class in "my" directory (eg.src\java\pl\agent_l\illegalaccess) yet declare its package as com.example.yoursecretengine - and gain access to all the properties you've meant as package private.
In fact, a Kotlin project works perfectly without ANY package declarations. This only highlights that packages are "more what you'd call guidelines than actual rules". They're a convenience feature, useful only to unclutter namespace and nothing more.
Relevant quotes from kotlinlang:
unlike many other languages, Kotlin packages do not require files to have any specific locations w.r.t. itself; the connection between a file and its package is established only via a package header.
And:
an absence of a package header in a file means it belongs to the special root package.

Android - Using a method from a Library

I have setup my own android library and now want to use the methods within..
For some reason I am having issues understanding how this works, looking at other questions/ internet has not helped.
In my library class i have the following.
public void testMethod(){
Toast s = Toast.makeText(this, "test!", Toast.LENGTH_SHORT).show();
}
I want to be able to reference this in my main for example, how do i do this?
I have found several links which do look at this however it has not helped as it is different to what I want to do. Am I being very stupid and missing something?
I am guessing an interface needs to be setup on my Main Class? I am not sure.
By the way I have already setup the library and have referenced in manifest etc..
You should import to your project the package name you used to create your library, then, create an object of the class you want to use from your library, and finally, call the method.
Supose your library package name it's: "com.mylibrary"
Your library class it's called: "MyClass"
Your method it's called: "MyMethod"
In Your Project you should do:
//Import Your Library Package
import com.mylibrary;
//Instantiate The Library Class
MyClass mytest = new MyClass();
//Call The Library Class Method You Want To Use.
mytest.MyMethod();

Android AOSP compilation error - can't find import in aidl file

I am trying to modify AOSP by adding a new system service.
I have the aidl for the service as follows :
package android.app;
import java.util.ArrayList;
import android.app.TypeA;
import android.app.TypeB;
interface myService {
ArrayList<TypeA> getA();
ArrayList<TypeB> getB();
}
TypeA and TypeB are implementing Parcelable interface, still when I try to build Android, it fails to import these 3:
couldn't find import for class java.util.ArrayList
couldn't find import for class android.app.TypeA
couldn't find import for class android.app.TypeB
I have looked at other related questions on SO and so far have not found an answer that works for me.
Does anyone know how to resolve this ?
I can see one problem and I'll guess at a second:
ArrayList, TypeA and TypeB are not Parcelable. All of the objects you pass around, via Binder, must implement the Parcelable interface.
In order for AIDL to work, you must declare every object used in an AIDL definition, in an AIDL file. If, for instance, TypeA did implement Parcelable, you still need an AIDL file for it
Like this:
package my.app;
parcelable TypeA;

not understanding compile errors in AIDL files

I'm taking my first foray into Android services and having trouble with compile errors in AIDL files. I am using Eclipse (with Android Development Tools) and Android 4.1. I have the following AIDL files:
Weather.aidl
package ws.hamacher.weatherservice.service;
parcelable ws.hamacher.weatherservice.dto.Weather;
In this file, I get "interface ws.hamacher.weatherservice.dto.Weather should be declared in a file called ws\hamacher\weatherservice\service\ws.aidl." on the parcelable line, but this refers to my Java class!
IWeatherService.aidl
package ws.hamacher.weatherservice.service;
import ws.hamacher.weatherservice.service.Weather;
interface IWeatherService {
void addToWeatherService(in Weather weather);
void deleteFromWeatherService(in Weather weather);
List<Weather> getLocations();
}
Here again, the import statement gives a similar error "interface ws.hamacher.weatherservice.dto.Weather should be declared in a file called ws\hamacher\weatherservice\service\ws.aidl." This should be referring to the first file above right?
Along with that, the method declarations all have errors, to the tune of "unknown type Weather".
Any help would be appreciated.
If you want to send custom object such as Weather class, you should creat a package:
ws.hamacher.weatherservice.dto
write :
Weather.java
in package: ws.hamacher.weatherservice.dto like this:
public class Weather implements Parcelable {
....
}
Then, write Weather.aidl:
package ws.hamacher.weatherservice.dto;
parcelable Weather;
Please see AndroidMusicPlayer and AndroidMusicPlayerClient for real code.
Solved it. My Weather.aidl had to be in the same directory as my parcelable Weather class.

Categories

Resources