AIDL unable to find the definition of a Parcelable class - android

I have the following project structure.
My StockInfo.java is perfectly fine.
StockInfo.java (No error)
package org.yccheok.jstock.engine;
import android.os.Parcel;
import android.os.Parcelable;
public class StockInfo implements Parcelable {
...
...
StockInfo.aidl (No error)
package org.yccheok.jstock.engine;
parcelable StockInfo;
StockInfoObserver.aidl (Error!)
package org.yccheok.jstock.engine;
interface StockInfoObserver {
void update(StockInfo stockInfo);
}
AutoCompleteApi.aidl (Error!)
package org.yccheok.jstock.engine;
interface AutoCompleteApi {
void handle(String string);
void attachStockInfoObserver(StockInfoObserver stockInfoObserver);
}
However, Eclipse complains in StockInfoObserver.aidl (It does complain AutoCompleteApi.aidl too, as it cannot process StockInfoObserver.aidl),
parameter stockInfo (1) unknown type StockInfo
I tried for an hour, but still not able to find out, why in aidl, StockInfo is not being recognized although I had
Provided StockInfo.aidl
Provided StockInfo.java
Any idea?
Here are the complete errors.
Note, AutoCompleteApi.aidl is very much dependent on StockInfoObserver.aidl. That's why you will see the error.
I share the entire project for your reference purpose : https://www.dropbox.com/s/0k5pe75jolv5mtq/jstock-android.zip

According to Android documentation You must include an import statement for each additional type not listed above, even if they are defined in the same package as your interface
Try to add this line to StockInfoObserver.aidl
import org.yccheok.jstock.engine.StockInfo;

Related

Running an android service in kivy written in java - too much?

I'm trying to build an NFC card emulator in kivy (similar to https://github.com/okanatas/NFCCardEmulator).
I can't simply subclass HostApduService (i.e.)
from jnius import autoclass
HostApduService=autoclass(android.nfc.cardemulation.HostApduService)
class NfcService(HostApduService):
def processCommandApdu(self, commandApdu, extras):
# Process the incoming APDU command
# and return a response APDU
# Example: Respond with the same data as received
return self.getBytes(commandApdu)
so instead I've tried to include some java files (similar to to the ones in the github) i.e.
package nfccardemulator;
import android.nfc.cardemulation.HostApduService;
import android.os.Bundle;
public class HostCardEmulatorService extends HostApduService {
#Override
public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {
...
}
}
and some other utilities files in Java.
I've put them in the services/nfccardemulator folder and added the following to buildozer:
android.add_src = services
I've checked the apk, and the classes are compiled and present. But I'm struggling to access them via autoclass
If I say
HostCardEmulatorService = autoclass("nfccardemulator.HostCardEmulatorService")
I get an error instantiating it.
I'm not sure if I'm even setting up a Service like this correctly.
I've seen an example of PythonService i.e.
PythonService = autoclass('org.kivy.android.PythonService')
and then having to use multiprocessing on the service while the kivy process runs separately.
Is what I'm trying to do even possible currently?
Thanks

Qt/C++/Android - How to install an .APK file programmatically?

I am implementing my own auto-updater within my application. I was able to successfully download the .apk file of the newer version into the /Download folder on the sdcard, but I can't figure out how to open/run that file so the user is presented with the new installation dialog.
The only thing I could come up with:
QString downloadedAPK = "/storage/emulated/0/Download/latest.apk"; // Not hardcoded, but wrote it here this way for simplicity
QDesktopServices::openUrl(QUrl(downloadedAPK));
Debugger output:
D/Instrumentation(26418): checkStartActivityResult :Intent { act=android.intent.action.VIEW dat=file:///storage/emulated/0/Download/latest.apk }
D/Instrumentation(26418): checkStartActivityResult inent is instance of inent:
W/System.err(26418): android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=file:///storage/emulated/0/Download/latest.apk }
W/System.err(26418): at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1660)
W/System.err(26418): at android.app.Instrumentation.execStartActivity(Instrumentation.java:1430)
W/System.err(26418): at android.app.Activity.startActivityForResult(Activity.java:3532)
W/System.err(26418): at android.app.Activity.startActivityForResult(Activity.java:3493)
W/System.err(26418): at android.app.Activity.startActivity(Activity.java:3735)
W/System.err(26418): at android.app.Activity.startActivity(Activity.java:3703)
W/System.err(26418): at org.qtproject.qt5.android.QtNative.openURL(QtNative.java:110)
W/System.err(26418): at dalvik.system.NativeStart.run(Native Method)
I have looked everywhere but never found anything regarding opening APKs from Qt. The only thing I found was a solutoin using JNI ( which I don't want to use because it's simpler to just do it with C++ and because I have zero experience with the whole C++/JNI thing ) and it was not well documented so I didn't understand how to make it work.
So, what would be the easiest way to open the downloaded apk?
Edit:
I have followed Tumbus's answer, but because of some compiling errors I had to make a few modifications on his JNI code as follows:
void Updater::InstallApp(const QString &appPackageName)
{
qDebug() << "[+] APP: " << appPackageName; // Which is the string ("/storage/emulated/0/Download/latest.apk")
QAndroidJniObject app = QAndroidJniObject::fromString(appPackageName);
QAndroidJniObject::callStaticMethod<jint>("AndroidIntentLauncher",
"installApp",
"(Ljava/lang/String;)I",
app.object<jstring>());
}
When I run my application on my android device, it pulls the newest .apk file from my server, then nothing happens. Why? (I have not made any changes on the AndroidManifest.xml until now).
You have to make a custom intent to install APK. See this question for details.
I'm afraid such platform-specific think must require calls to platform-specific API. The good news are Qt framework has simplified wrap-up on JNI and you can include a Java class into Android project. Therefore I would make my own static java function called from Qt.
Example
Java class
package io.novikov.androidintentlauncher;
import org.qtproject.qt5.android.QtNative;
import java.lang.String;
import java.io.File;
import android.content.Intent;
import android.util.Log;
import android.net.Uri;
import android.content.ContentValues;
import android.content.Context;
public class AndroidIntentLauncher
{
protected AndroidIntentLauncher()
{
}
public static int installApp(String appPackageName) {
if (QtNative.activity() == null)
return -1;
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(appPackageName)),
"application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
QtNative.activity().startActivity(intent);
return 0;
} catch (android.content.ActivityNotFoundException anfe) {
return -3;
}
}
}
Notice that startActivity() should be called as a method from *QtNative.activity(). We have to maintain special directory structures for java according to conventional rules. The example is at Makefile section below.
JNI
The C++ code to call this method is a bit tricky.
const static char* MY_JAVA_CLASS = "io/novikov/androidintentlauncher/AndroidIntentLauncher";
static void InstallApp(const QString &appPackageName) {
QAndroidJniObject jsText = QAndroidJniObject::fromString(appPackageName);
QAndroidJniObject::callStaticMethod<jint>(MY_JAVA_CLASS,
"installApp",
"(Ljava/lang/String;)I",
jsText.object<jstring>());
}
The string literal "(Ljava/lang/String;)I" is the signature of java method.
The name of the Java class must be at a complete form "my/domain/my_app/MyClass"
Makefile
The last challenge is to include the java code to your project properly. Below the corresponding fragment of the .pro file.
android {
QT += androidextras
OTHER_FILES += android_src/src/io/novikov/androidintentlauncher/AndroidIntentLauncher.java
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android_src
}
QMake has a special variable ANDROID_PACKAGE_SOURCE_DIR for this job. Java sources must reside in ANDROID_PACKAGE_SOURCE_DIR/src/my/domain directories.
Also don't forget to add java source to OTHER_FILES and include androidextras QT option.

Endpoint.Builder missing for generated cloud endpoint

I'm attempting to follow the example tutorial at https://developers.google.com/eclipse/docs/endpoints-addentities and I'm stuck figuring out how to get the GameEndpoint.Builder class to generate within Eclipse.
After following this and generating the cloud endpoints as described, I have a GameEndpoint class created, but there is no GameEndpoint.Builder class. So obviously I have this error
GameEndpoint.Builder cannot be resolved to a type
I'm stumped at this point. How do I generate the GameEndpoint.Builder class within Eclipse, or what would prevent it?
Code
public class NewGameTask extends AsyncTask<Context, Integer, Long> {
protected Long doInBackground(Context... contexts) {
GameEndpoint.Builder endpointBuilder = new GameEndpoint.Builder(
AndroidHttp.newCompatibleTransport(), new JacksonFactory(),
new HttpRequestInitializer() {
public void initialize(HttpRequest httpRequest) {
}
});
GameEndpoint endpoint = CloudEndpointUtils.updateBuilder(
endpointBuilder).build();
try {
Game game = new Game();
game.setStart(Calendar.getInstance());
Game result = endpoint.insertGame(game);
} catch (IOException e) {
e.printStackTrace();
}
return (long) 0;
}
}
I figured out my issue after watching this video from Google I/O 2013 which is using Android Studio, but it was the same thing as Eclipse mostly.
My mistake in following https://developers.google.com/eclipse/docs/endpoints-addentities was that you need to put your entity class into the MyApp-AppEngine project and NOT your MyApp project.
That was the source of confusion. In case it helps those in the future, here is a short breakdown of what I did.
Put the Entity class you want to add to App Engine into your MyApp-AppEngine project.
Right click your class and go to Google > Generate Cloud Endpoint Client Library
Right click your MyApp-AppEngine project and go to Google > Generate Cloud Enpoint Client Library
New references will be made in your MyApp project which you reference in your project for usage.
Note This answer is based on Android Studio, but am sure it's pretty much the same as Eclipse.
I also had this issue but later found the cause.Turns out I was importing the Endpoint class I generated instead of the endpoint Api package. Let me be clear.When you add the endpoint module to your project, you get the MyBean and MyEndpoint classes in the endpoint package. If you take a look at the guide to connecting your client to your backend, the EndpointsAsyncTask class uses:
private static MyApi myApiService = null;
Note how it uses MyApi instead of MyBean Now I was wondering where it got that from but I just have to take a look at my backend libraries:
The library marked 1 is the library first added to your project when you follow the guide previously mentioned. When I added a new class Student and autogenerated the cloud endpoint class, the second library was also added.
Long, boring story short; It is this library you should be importing and not the class.
import com.package-name.backend.studentApi.StudentApi;
and then using:
private static StudentApi myApiService = null;
...
StudentApi.Builder builder = new StudentApi.Builder(...)
instead of:
import com.package-name.backend.StudentEndpoint;
...
private static StudentEndpoint myApiService = null;
StudentEndpoint.Builder builder = new StudentEndpoint.Builder(...)
I got the same problem in Android Studio. I generated my Endpoint class from my entity java bean but when creating the AsyncTask, now way to get the Builder.
Actually (if I take a Game java bean like you) the Builder is not depending on the GameEndPoint but on the generated GameApi class.
In other words, I had to add these two imports in the AsyncTask class:
import com.examplepackage.backend.gameApi.GameApi;
import com.examplepackage.backend.gameApi.model.Game;
while the Game java bean that you wrote and the generated GameEndpoint are under package com.examplepackage.backend

GoogleJsonResponseException: 404 Not Found using google apps endpoint engine backend

I followed the tutorial below.
https://developers.google.com/eclipse/docs/running_and_debugging_2_0
which basically added a GAE backend to my existing app. I then try out the example below, run it on the local development server and I get the exception below which occurs after
Note result = endpoint.insertNote(note).execute();
is called.
com.google.api.client.googleapis.json.GoogleJsonResponseException: 404 Not Found
My code is below.
package com.cloudnotes;
import java.io.IOException;
import java.util.Date;
import android.os.AsyncTask;
import android.content.Context;
import com.cloudnotes.noteendpoint.Noteendpoint;
import com.cloudnotes.noteendpoint.model.Note;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.json.jackson.JacksonFactory;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new EndpointsTask().execute(getApplicationContext());
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
public class EndpointsTask extends AsyncTask<Context, Integer, Long> {
protected Long doInBackground(Context... contexts) {
Noteendpoint.Builder endpointBuilder = new Noteendpoint.Builder(
AndroidHttp.newCompatibleTransport(),
new JacksonFactory(),
new HttpRequestInitializer() {
public void initialize(HttpRequest httpRequest) { }
});
Noteendpoint endpoint = CloudEndpointUtils.updateBuilder(
endpointBuilder).build();
try {
Note note = new Note().setDescription("Note Description");
String noteID = new Date().toString();
note.setId(noteID);
note.setEmailAddress("E-Mail Address");
Note result = endpoint.insertNote(note).execute();
} catch (IOException e) {
e.printStackTrace();
}
return (long) 0;
}
}
}
Another possible cause for this problem is not setting the correct applicationId in appengine-web.xml:
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<application>APPLICATION_ID_HERE</application>
...
</appengine-web-app>
Another possible reason for 404 if you call the method with a null parameter and the method does not accept null parameters.
I had a similar issue with a method with 4 String parameters and I sent null for one of them and all I got was a stupid 404.
Another possible reason for 404 on the development(local) server is that you have a parameter with some strange characters (like a url for example) that the development(local) server does not handle correctly event if it works fine on the app engine live servers. Possible solution: instead of multiple params use a simple java object.
I had the same problem and this is how I fixed it.
A little background
I had two versions of the API deployed to App Engine which I believe it should be OK. The admin console didn't show any problem and I was getting the 200 OK code after deploying version 2 of the API in log file.
/_ah/spi/BackendService.getApiConfigs 200 118ms 8kb
but no matter what I tried I was always getting the 404 Not Found error.
I am not sure what the problem was but I think Web Server at App Engine was redirecting all the requests to the version 1. It could be because both versions had the following settings in their web.xml.
<servlet-mapping>
<servlet-name>SystemServiceServlet</servlet-name>
<url-pattern>/_ah/spi/*</url-pattern>
</servlet-mapping>
Solution
I removed version 1 and redeployed version 2. Then everything just worked fine.
This comes down to the app engine default version being different from the one you've deployed. Go here:
https://appengine.google.com/deployment?app_id=s~your-project-id
and change your default version
this happen because your deploy back-end is not fully deployed. just re-deploy your back-end and make sure you got the message deploy succeed. you can check the detail deploy process on the top page header. also, you can test by visiting the url to check:
https://developers.google.com/apis-explorer/?base=https://[YOUR_PROJECT_ID].appspot.com/_ah/api#p/
Try to update your plugin and dependency libraries to the latest version. See https://stackoverflow.com/a/37639701/857346.
In build gradle do:
minifyEnabled false

android jdbc odbc connection

i want to connect odbc connection to my android application. my database is oracle 10g. Here in my code my table name is world. After compiling my program and close the emulator open table in oracle database the values could not be stored
The same coding i compiled normal javac compiler in cmp prompt the values should be stored, if i compiling in android application in eclipse ide the values could not be stored.Pls give one solution or any changes in my code
Thanks in advance
package com.odbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import android.app.Activity;
import android.os.Bundle;
import android.R.id;
public class OdbcActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try
{
String country="india";
String city="delhi";
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection con=DriverManager.getConnection("jdbc:odbc:world","system","love");
PreparedStatement ps=con.prepareStatement("insert into world(country,city) values(?,?)");
ps.setString(1,country);
ps.setString(2,city);
ps.executeUpdate();
}
catch(Exception e)
{
System.out.println("Exception:"+e);
}
}
}
Android apps connecting directly to a DMBS isn't an architecture I'd recommend. Instead, I suggest setting an application on the server (using Java, Rails, whatever) that reads the database and exposes a simple HTTP web service for the Android app to get at the data. Not only is that a more sound architecture, I'm not even sure you can run JDBC drivers in an Android device. Using my architecture, you isolate the device from the structure and type of your database.

Categories

Resources