I'm trying to create a remote service in Eclipse using Android AIDL. I have created my AIDL file IRemoteService.aidl in /src as follows:
package com.vtrandal.bluesentry;
interface IRemoteService {
String getData();
}
After doing a build I get an enormous file IRemoteService.java in /gen containing these classes and methods as follows (it doesn't resemble anything I've seen in the documentation):
public interface IRemoteService extends android.os.IInterface
public static abstract class Stub extends android.os.Binder implements com.vtrandal.bluesentry.IRemoteService
private static final java.lang.String DESCRIPTOR = "com.vtrandal.bluesentry.IRemoteService";
public Stub()
public static com.vtrandal.bluesentry.IRemoteService asInterface(android.os.IBinder obj)
public android.os.IBinder asBinder()
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
private static class Proxy implements com.vtrandal.bluesentry.IRemoteService
Proxy(android.os.IBinder remote)
public android.os.IBinder asBinder()
public java.lang.String getInterfaceDescriptor()
public java.lang.String getData() throws android.os.RemoteException
public java.lang.String getData() throws android.os.RemoteException;
So why does IRemoteService.java contain so much junk not mentioned in the documentation? How could I possibly know what to do with it all? How could I possibly know what to do with any of it?
This is service stub code. It is needed to actually communicate with client. You didn't write any code for communicating between client and service yourself,did you? It's not as simple, after all and it is being generated for you. That's why so much code.
And documentation usually discusses API for user, not stub internal methods.
Related
I'm using Green Coffee library to run Cucumber scenarios in my instrumentation tests. I followed example provided by repo step-by-step, but here's the error:
junit.framework.AssertionFailedError: Class pi.survey.features.MembersFeatureTest has no public constructor TestCase(String name) or TestCase()
And when I try to add default constructor to the class like provided here, it says
no default constructor available in
'com.mauriciotogneri.greencoffee.GreenCoffeeTest'
Here's my test's source code:
package pi.survey.features;
import android.support.test.rule.ActivityTestRule;
import com.mauriciotogneri.greencoffee.GreenCoffeeConfig;
import com.mauriciotogneri.greencoffee.GreenCoffeeTest;
import com.mauriciotogneri.greencoffee.Scenario;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.io.IOException;
import pi.survey.MainActivity;
import pi.survey.steps.memberSteps;
#RunWith(Parameterized.class)
public class MembersFeatureTest extends GreenCoffeeTest {
#Rule
public ActivityTestRule<MainActivity> activity = new ActivityTestRule<>(MainActivity.class);
public MembersFeatureTest(Scenario scenario) {
super(scenario);
}
#Parameterized.Parameters
public static Iterable<Scenario> scenarios() throws IOException {
return new GreenCoffeeConfig()
.withFeatureFromAssets("assets/members.feature")
.scenarios();
}
#Test
public void test() {
start(new memberSteps());
}
}
And my members.feature source:
Feature: Inserting info to server
Scenario: Invalid members
When I introduce an invalid members
And I press the login button
Then I see an error message saying 'Invalid members'
Regarding the questions about the constructors. Due to the fact that tests in GreenCoffee require:
#RunWith(Parameterized.class)
The static method annotated with #Parameters must return a list of something (but not necessarily Scenario). The examples in the documentation simply return a list of scenarios, that's why the constructor must take a single Scenario as a parameter.
However, you can create a class that encapsulates the scenario and other objects that you may need to pass to the constructor. For example, given the following class:
public class TestParameters
{
public final String name;
public final Scenario scenario;
public TestParameters(String name, Scenario scenario)
{
this.name = name;
this.scenario = scenario;
}
}
You can write:
public TestConstructor(TestParameters testParameters)
{
super(testParameters.scenario);
}
#Parameters
public static Iterable<TestParameters> parameters() throws IOException
{
List<TestParameters> testParametersList = new ArrayList<>();
List<Scenario> scenarios = new GreenCoffeeConfig()
.withFeatureFromAssets("...")
.scenarios();
for (Scenario scenario : scenarios)
{
testParametersList.add(new TestParameters(scenario.name(), scenario));
}
return testParametersList;
}
In this way you can receive multiple values (encapsulated in an object) in the test constructor.
Solved problem by just fixing the structure.
code details in this commit
I have the following in a class that is implementing Parcelable:
private static final long serialVersionUID = 66;
private HashMap<Integer, Bitmap> mBitmaps;
private HashMap<Integer, Drawable> mDrawables;
private Context mContext;
And:
#Override
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
dest.writeValue(mBitmaps);
dest.writeValue(mDrawables);
dest.writeValue(mContext);
dest.writeByte((byte) (mActive ? 0x01 : 0x00));
}
I get the error:
java.lang.RuntimeException: Parcel: unable to marshal value android.app.Application#4051cfe0
at android.os.Parcel.writeValue(Parcel.java:1132)
at com.example.example.ImageManager.writeToParcel(ImageManager.java:82)
dest.writeValue(mContext); is on line 82.
As stated in this answer: https://stackoverflow.com/a/6112919/7721253
You are trying to add to the parcel objects which are not serializable. Objects within the objects you are serializing have to be serializable as well.
You are writing to Parcel.
Did you implemeted Parcelable to do so ?
You need to implement the Serializable or Parcelable interface. Otherwise the value will not be marsheled as the error suggests.
Also,
Classes implementing the Parcelable interface must also have a static
field called CREATOR, which is an object implementing the
Parcelable.Creator interface.
Check about android Parcelable.
Just write a little Class thats holding your Context-Object like this:
import android.content.Context;
public class ContextHolder {
public static Context context = null;
public static void setContext(Context context){
ContextHolder.context = context;
}
public static Context getContext(){
return context;
}
}
then whenever you need the Context, you can just call the ContextHolder.getContext() function from everywhere you need it.
Cheers
I happen to know what if my class Info which implements Parcelable has empty writeToParcel() method, Bundle.putParcelableArrayList() and Bundle.getParcelableArrayList() methods still work on ArrayList< Info>.
public class Info implements Parcelable
{
public int row;
public int column;
public int describeContents()
{
return 0;
}
public void writeToParcel(Parcel out, int flags)
{
// Left empty!
}
}
So the question is why? When I really should implement writeToParcel method as API documentation and books instruct?
The Android Bundle class does not follow the same protocol that is followed during IPC marshaling. Through reflection, a class that implements Bundle will simply read & write the Parcelable object into its own internal mapping. So, whatever properties you define in your Parcelable derived class will be used.
On the contrary, if you're using the IPC Marshalling protocol - e.g. passing your Info object from one activity to another - this is when you need to implement a specific writeToParcelable method and the appropriate constructor.
I'm trying to create a custom audio effect by extending from the class android.media.audiofx.AudioEffect but for some reason the constructor for this class is not presenting the same signature I see in the source code here.
The AudioEffect class doesn't seem to have some of the public static final UUID constants that define each different effect, for example like the following:
public static final UUID EFFECT_TYPE_BASS_BOOST = UUID
.fromString("0634f220-ddd4-11db-a0fc-0002a5d5c51b");
I'm using the SDK for API 10 (v2.3.3) which should work since every out-of-the-box effect that exists in android extends from this class.
public class BassBoost extends AudioEffect {
...
public BassBoost(int priority, int audioSession)
throws IllegalStateException, IllegalArgumentException,
UnsupportedOperationException, RuntimeException {
super(EFFECT_TYPE_BASS_BOOST, EFFECT_TYPE_NULL, priority, audioSession);
int[] value = new int[1];
checkStatus(getParameter(PARAM_STRENGTH_SUPPORTED, value));
mStrengthSupported = (value[0] != 0);
}
...
}
Maybe I'm missing something, but I can't figure out what it is.
Any help will be appreciated.
Thanks.
Because of the #hide annotations those constants are not available in the public sdk api.
I am creating an AIDL interface that uses an object type from an android library that is part of a different project. I can import and use the type fine in my service, but I can not import it in my AIDL interface.
package com.mysite.service;
import com.othersite.library.MyObject;
interface IMyService {
int getPid();
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
MyObject getObjects();
}
The error is:
couldn't find import for class com.othersite.library.MyObject
You must create a separate .aidl file for each class you wish to use
within your service that declares that class as parcelable.
There is a blog post about this issue here.