java.lang.NoClassDefFoundError with all R classess when using android library - android

I downloaded a source code from a library for android, compiled it and I got a .jar file, I included into my project and I tried to use it but I always get a java.lang.NoClassDefFoundError, I noticed that in the jar file there are not R$XXX files, I read this post: Android Library Import delete R and tried the solutions but none worked for me.
I made my own simple library and I saw that either, the R files are not included in the jar, I have to add the .class files manually using winrar but I think I am missing something simple, I am using eclipse with ADT.
Thanks to everyone

If you are creating jar files then you should not include r.java,manifeast file in the jar file.
Because the jar wont get complied during compliation and wont create any static integer during compliation time.
In android we have Android LIbrary which is similar to android project but can be included in other projects.
And if still you need to have jar file then just keep class files in jar include all your resource contain in application and from java files you can use the below code to refer the resources during runtime.
That you must use getResourseIdByName(getPackageName(), "drawable", "icon") instead of R.drawable.icon in your code.
Below is the code for getResourceIdByName::
public int getResourseIdByName(String packageName, String className, String name) {
int id = 0;
try {
for (int i = 0; i < Class.forName(packageName + ".R").getClasses().length; i++) {
if(Class.forName(packageName + ".R").getClasses()[i].getName().split("\\$")[1].equals(className)) {
if(Class.forName(packageName + ".R").getClasses()[i] != null)
id = Class.forName(packageName + ".R").getClasses()[i].getField(name).getInt(Class.forName(packageName + ".R").getClasses()[i]);
break;
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return id;
}

Related

how to use guardianproject's android ffmpeg library?

First, this is my first time "playing" with ffmpeg, so please bear with me.
Generally, i dont understand ffmpeg even a little bit. So i did lot, lot of researches (and also trial & error) and i finally found this project and its library
So i was successfully created the ffmpeg and sox binary file, and i put it in the raw folder at the library project (from the link i shared).
Now, i want to use the library for my project, but i still cant do it. I tried to use some methods in the FfmpegController like combineAudioAndVideo and more but its not working (yet).
I dont post the error here since i still do my trial&errors (and the error change regularly) but im getting tired now.
EDIT
This is what i did :
private FfmpegController ffController;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
File file = new File(Uri.parse("android.resource://com.my.package/" + R.raw.test).getPath());
try {
ffController = new FfmpegController(this, file);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
MediaDesc desc = ffController.combineAudioAndVideo(R.raw.test, R.raw.musictest, "test.mp4", null);
}
The combineAudioAndVideo always error because wrong parameters. It needs MediaDesc but i dont know how to do it.
I will be very happy if you can share your working code if you have done the ffmpeg processing with this library.

Using EWS to send mail from exchange server

I followed this link to generate the jar file. I added this to my project. Then have a simple code to send a mail:
public void mailSend() {
ExchangeService service = new ExchangeService();
ExchangeCredentials credentials = new WebCredentials(
"email", "$*pass!");
service.setCredentials(credentials);
String host = "host";
try {
service.setUrl(new java.net.URI("https://" + host
+ "/EWS/Exchange.asmx"));
service.setTraceEnabled(true);
EmailMessage msg = new EmailMessage(service);
msg.setSubject("Hello world!");
msg.setBody(MessageBody
.getMessageBodyFromText("Sent using the EWS Managed API."));
msg.getToRecipients().add("email");
msg.send();
Log.i("Msg","SEND ");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
The problem is that it shows the jar file has no source attachment. Hence I get the error no definition found for class ExchangeService. This should be part of the jar file generated. While exporting as jar file, I had made sure the src folder is clicked.

How can i Load a jar file dynamically in an android application (4.0.3)

I have an android application which has to load dynamically class ,an undefined number of a jar class which implemented an interface.
In fact, I look at a directory and list all the jar files which are in this directory
I open the manifest of the jar file and find the associated class and list them.
And after, i instancied a dexClassLoader to load all the jar files and to find if the classes i have found in the manisfest implement my interface.
Like this I can have all the class which implemented my interface without knowing them at the begginning
To resume, i have a list of class jar which implement my interface but the list is unknown by my android application and by me. The list of jar class can changed each time i launch my application.
But when i tried to create the DexClassLoader it is failed. I have always a null pointer
DexClassLoader classLoader = new DexClassLoader(dexInternalStoragePath.getAbsolutePath(),dexOutputDir.getAbsolutePath(), null, ClassLoader.getSystemClassLoader());
To make my test i used the emulator. I have copied with my DDMS the jar files into the directory
/data/data/com.example.Myappli/JarFilesDirectory/*.jar
Notice that my jar file contents the dex file
I read a lot of thing about this. Some permissions issues
I have tried every thing but not found the solution
Can someone help me please !!!
here the content of a manifest of a jar file
Manifest-Version: 1.0
Module-Class: com.example.asktester.AskPeripheral
Here my code :
public class ModuleLoader {
private static List<URL> urls = new ArrayList<URL>();
private static List<String> getModuleClasses(String folder)
{
List<String> classes = new ArrayList<String>();
//we are listing the jar files
File[] files = new File(folder).listFiles(new ModuleFilter());
for(File f : files)
{
JarFile jarFile = null;
try
{
//we open the jar file
jarFile = new JarFile(f);
//we recover the manifest
Manifest manifest = jarFile.getManifest();
//we recover the class
String moduleClassName = manifest.getMainAttributes().getValue("Module-Class");
classes.add(moduleClassName);
urls.add(f.toURI().toURL());
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if(jarFile != null)
{
try
{
jarFile.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
return classes;
}
private static class ModuleFilter implements FileFilter {
#Override
public boolean accept(File file) {
return file.isFile() && file.getName().toLowerCase().endsWith(".jar");
}
}
private static ClassLoader classLoader;
public static List<IPeripheral> loadModules(String folder, Context CurrentContext) throws IOException, ClassNotFoundException
{
List<IPeripheral> modules = new ArrayList<IPeripheral>();
List<String> classes = getModuleClasses(folder);
final File dexInternalStoragePath = new File(CurrentContext.getDir("dex", Context.MODE_PRIVATE),"ask.dex");
File dexOutputDir = CurrentContext.getDir("dex", Context.MODE_PRIVATE);
final File dexClasses = new File(CurrentContext.getDir("dex", Context.MODE_PRIVATE),"ASK.jar");
DexFile dexFile = DexFile.loadDex(dexClasses.getAbsolutePath(), dexOutputDir.getAbsolutePath(), 0);
DexClassLoader classLoader = new DexClassLoader(dexInternalStoragePath.getAbsolutePath(),dexOutputDir.getAbsolutePath(), null, ClassLoader.getSystemClassLoader());
//Class<?> myClass = classLoader.loadClass("com.example.asktester.AskPeripheral");
if(IPeripheral.class.isAssignableFrom(myClass )){
Class<IPeripheral> castedClass = (Class<IPeripheral>)myClass ;
IPeripheral module = castedClass.newInstance();
modules.add(module);
}
}
catch (ClassNotFoundException e1)
{
e1.printStackTrace();
}
catch (InstantiationException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
}
return modules;
}
I found the solution to my issue.
To load dynamically jar, classes which implement an interface in an android application, some jobs need to be done in the jar :
Create your own manisfest for the jar and put this information
Manifest-Version: 1.0
Module-Class: com.example.myjar.MyPeripheral
Export your jar using eclipse and put in parameter that it uses its own manisfest
Create the classes.dex associated to the jar
(this file is needed by the Dalvik VM, simply jar can not be read by the dalvik VM)
dx --dex --output=C:\classes.dex C:\MyJar.jar
Be carefull, the name of the dex file MUST BE classes.dex
Add the file classes.dex in the jar file
aapt add C:\MyJar.jar C:\classes.dex
You need also to have the right to write into the dalvik cache directory
adb shell chmod 777 /data/dalvik-cache
Do it each time, your relaunch your emulator
put this jar file into the emulator for example on the SDcard
Use a PathClassLoader to load the jar file
dalvik.system.PathClassLoader myClassLoader = new dalvik.system.PathClassLoader("/Sdcard/MyJar.jar", ModuleLoader.class.getClassLoader());
NB : the LogCat in Eclipse gives you precious information. Do not forget to look at its messages
Below, the code :
My interface :
package com.example.StandartPeripheral;
public interface IPeripheral {
public boolean Initialize();
public boolean configure();
public boolean execute();
public String GetName();
}
MyPeripheral which implements the interface
public class MyPeripheral implements IPeripheral {
//public static void main(String[] args) {}
private final String PeripheralName = "MyPeripheral";
public boolean Initialize()
{
System.out.println("Initialize ");
return true;
};
public boolean configure()
{
System.out.println("Configure !");
return true;
};
public boolean execute()
{
System.out.println("Execute !");
return true;
};
public String GetName()
{
return PeripheralName;
}
}
How to load dynamically the jar files
package com.example.ModuleLoader;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import com.example.StandartPeripheral.IPeripheral;
public class ModuleLoader {
private static List<URL> urls = new ArrayList<URL>();
// to retrieve the unknown list of jar files contained in the directory folder
// in my case it was in the SDCard folder
// link to create a SDCard directory on the Eclipse emulator
// http://blog.lecacheur.com/2010/01/14/android-avoir-acces-a-une-carte-memoire-dans-lemulateur/
// retrieve the classes of all this jar files and their URL (location)
private static List<String> getModuleClasses(String folder)
{
List<String> classes = new ArrayList<String>();
//we are listing the jar files
File[] files = new File(folder).listFiles(new ModuleFilter());
for(File f : files)
{
JarFile jarFile = null;
try
{
//we open the jar file
jarFile = new JarFile(f);
//we recover the manifest
Manifest manifest = jarFile.getManifest();
//we recover the class name of our peripherals thanks to ours manifest
String moduleClassName = manifest.getMainAttributes().getValue("Module-Class");
classes.add(moduleClassName);
urls.add(f.toURI().toURL());
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if(jarFile != null)
{
try
{
jarFile.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
return classes;
}
private static class ModuleFilter implements FileFilter {
#Override
public boolean accept(File file) {
return file.isFile() && file.getName().toLowerCase().endsWith(".jar");
}
}
//This function loads the jar file into the dalvik system
// retrieves the associated classes using its name
// and try to know if the loaded classes are implementing our interface
public static List<IPeripheral> loadModules(String folder, Context CurrentContext) {
List<IPeripheral> modules = new ArrayList<IPeripheral>();
List<String> classes = getModuleClasses(folder);
int index = 0;
for(String c : classes)
{
try
{
dalvik.system.PathClassLoader myClassLoader = new dalvik.system.PathClassLoader(urls.get(index).toString(), ModuleLoader.class.getClassLoader());
Class<?> moduleClass = Class.forName(c, true, myClassLoader);
//check and cast to an interface, then use it
if(IPeripheral.class.isAssignableFrom(moduleClass))
{
#SuppressWarnings("unused")
Class<IPeripheral> castedClass = (Class<IPeripheral>)moduleClass;
IPeripheral module = (IPeripheral)moduleClass.newInstance();
modules.add(module);
}
index++;
}
catch (ClassNotFoundException e1)
{
e1.printStackTrace();
}
catch (InstantiationException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
}
return modules;
}
}
It would also be a good idea to use the ClassLoader rather than the Dalvik path class loader:
ClassLoader cl = new DexClassLoader(url, ApplicationConstants.ref_currentActivity.getFilesDir().getAbsolutePath(), null, ModuleList.class.getClassLoader());
Where url is the location of the file you are loading "from".
ApplicationConstants.ref_currentActivity is simply an activity class - my implementation is fairly complicated due to dynamic modular loading - so I needed to keep track of it this way - but others can probably just use "this" if that class is already an activity.
The MAIN reason for using the class loader over the dalvik one - is that it doesn't require files to be written to cache, and therefore the permission chmod 777 /data/dalvik-cache is unrequired - and of course you also wouldn't need to pass this command from root on a rooted phone pro-grammatically either.
It's always best to not have users forced to root their phones, simply because your app requires it. Especially if your app is a more professional "meant-for-company-use-type" -.Work Policies against the use of rooted phones are usually in place too.
If anyone has any questions on modular loading - please feel free to ask.
The base of my current code is all thanks to Virginie Voirin, along with my own modifications. Good luck all!

PDFBox for processing pdf in android

i am trying to use pdfbox lib into my android app but im getting
java.lang.NoClassDefFoundError: org.pdfbox.pdmodel.PDDocument
this error .as i'm developing commercial app i can not use other Lib like itext .So my question is can we use PDfBox in android.
here is my code:-
PDFParser parser = null;
String parsedText = null;
PDFTextStripper pdfStripper;
PDDocument pdDoc = null;
COSDocument cosDoc = null;
PDDocumentInformation pdDocInfo;
try {
f =new File(Environment.getExternalStorageDirectory()+File.separator+"Download"+File.separator+"Services.pdf");
if(f.exists()){
System.out.println("---------exists-----------");
}else{
System.out.println("------NOT----exists----------");
}
parser = new PDFParser(new FileInputStream(f));
} catch (Exception e) {
System.out.println("Unable to open PDF Parser.");
System.out.println("-----------------------error|"+e.toString());
}
try {
parser.parse();
cosDoc = parser.getDocument();
pdfStripper = new PDFTextStripper();
pdDoc = new PDDocument(cosDoc);//here i'm getting exception
//pdDoc = PDDocument.load(f, false);
parsedText = pdfStripper.getText(pdDoc);
} catch (Exception e) {
System.out.println("-----------------------error|"+e.toString());
System.out.println("An exception occured in parsing the PDF Document.");
e.printStackTrace();
try {
if (cosDoc != null) cosDoc.close();
if (pdDoc != null) pdDoc.close();
} catch (Exception e1) {
e.printStackTrace();
}
}
System.out.println("Done.");
System.out.println("-----------------------parsedText|"+parsedText);
using PDFBox 0.7.3 jar
It seems that PDFBox is depending on awt and swing classes that are not available on Android devices.
Therefor you can not use PDFBox on Android.
NoClassDefFoundError is thrown when the JVM can't load a class.
As the javadoc says
Have you included the pdfbox library on classpath during compilation?
If you only need to extract text from PDF document in Android , then use this https://github.com/RatheeshRavindran/PDFBoxLight
I recently did the porting of PDFBox to Android but please note that this still in Beta.

Android- Using DexClassLoader to load apk file

I've hit a bit of a wall. Any help would be appreciated. I have an app that I want to use DexClassLoader to load another apk file.
Here is my code:
DexClassLoader dLoader = new DexClassLoader("/sdcard/download/test.apk","/sdcard/download",null,ClassLoader.getSystemClassLoader().getParent());
Class calledClass = dLoader.loadClass("com.test.classname");
Intent it=new Intent(this, calledClass);
it.setClassName("com.test", "com.test.classname");
startActivity(it);
Now I had already installed test.apk so when I ran the above code it
worked fine and launched the application. However I want to be able to
run this without test.apk being installed already (as that would
defeat the entire point of the application) . So I uninstalled it and
when I ran the my app again I get this error:
android.content.ActivityNotFoundException: Unable to find explicit
activity class {com.test/com.test.classname}; have you declared this
activity in your AndroidManifest.xml.
So I'm a bit stumped here. This activity is declared in the Manifest
of the apk I am trying to run. I can't declare it in my applications
Manifest. Any ideas?
Thanks,
Craig
Try using Android's PathClassLoader:
String packagePath = "com.mypackage";
String classPath = "com.mypackage.ExternalClass";
String apkName = null;
try {
apkName = getPackageManager().getApplicationInfo(packagePath,0).sourceDir;
} catch (PackageManager.NameNotFoundException e) {
// catch this
}
// add path to apk that contains classes you wish to load
String extraApkPath = apkName + ":/path/to/extraLib.apk"
PathClassLoader pathClassLoader = new dalvik.system.PathClassLoader(
apkName,
ClassLoader.getSystemClassLoader());
try {
Class<?> handler = Class.forName(classPath, true, pathClassLoader);
} catch (ClassNotFoundException e) {
// catch this
}
Although the question is old, I will answer because I struggled a bit to find a clear answer for your same question for myself. First, I would like to highlight that a clear requirement in your question is to load a class from an .apk that is not already installed on the device. Therefore, calling the package manager using getPackageManager() and providing it with the package path will clearly lead to NameNotFoundException because the .apk that has the package is not installed on the device.
So, the way to go about loading classes from an .apk file that is not installed on the device (i.e. you only have the .apk stored in a directory on your SDCARD) is by using DexClassLoader as follows:
1- Make sure you have the .apk file in a directory on your SDCARD. I've mine Offloadme.apk in the Download folder on my SDCARD.
2- Add read permission in your AndroidManifest.xml to allow your app to read from the manifest.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
3- Use the following definitions to define the path of the .apk, the class name inside the apk, and method name in that class that you would like to invoke:
final String apkFile =Environment.getExternalStorageDirectory().getAbsolutePath()+"/Download/Offloadme.apk";
String className = "com.khaledalanezi.offloadme.SimpleCalculator";
String methodToInvoke = "add";
4- Use the DexClassLoader to load the .apk and call the add method in the SimpleCalculator class using reflection as follows:
final File optimizedDexOutputPath = getDir("outdex", 0);
DexClassLoader dLoader = new DexClassLoader(apkFile,optimizedDexOutputPath.getAbsolutePath(),
null,ClassLoader.getSystemClassLoader().getParent());
try {
Class<?> loadedClass = dLoader.loadClass(className);
Object obj = (Object)loadedClass.newInstance();
int x =5;
int y=6;
Method m = loadedClass.getMethod(methodToInvoke, int.class, int.class);
int z = (Integer) m.invoke(obj, y, x);
System.out.println("The sum of "+x+" and "+"y="+z);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Note that in my simple example, I added two numbers using the add method available in the SimpleCalculator class loaded from the Offloadme.apk file stored on my SDCARD and I was able to print the correct answer which is 11.
You can't do that. Even if you're able to access classes from external file, Android still does not know them. And you don't run activities directly, but by requesting Android to run them, so they have to be registered/installed into system.

Categories

Resources