I am using android-json-rpc library. I added the android-json-rpc-0.3.4.jar library to my build path. Just following some basic tutorial.
Here is my code:
public class MainActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.text_view);
tv.setText(testMethod());
}
private String testMethod() {
// Crashes here on this line
JSONRPCClient client = JSONRPCClient.create("10.1.2.3/json", JSONRPCParams.Versions.VERSION_2);
String string = "";
try {
string = client.callString("cf.test");
} catch (JSONRPCException e) {
Log.i("JSON-RPC Client", e.toString());
}
return string;
}
}
Error:
*AndroidRuntime(1528): java.lang.NoClassDefFoundError: org.alexd.jsonrpc.JSONRPCParams$Versions*
While going around this error, I found out that some guy has a blogpost about the same issue on a Mac Lion (same as mine) but worked fine on Ubuntu. http://www.1771.in/android-jsonrpc-not-working-on-mac.html
Could anyone help me with a workaround for this issue?
Thanks,
Dexter
There are 2 options I have in mind. 1. Have "libs" folder in root of the project, copy lib there, no need to add to the build path. This is a new requirement from android team. 2. Add import of used class.
Just got it compiled and working.
Related
I'm running some tests with Roboletric, but I came across a issue that I can't solve.
When I run the test, the following error appears with the "AndroidManifest":
WARNING: No manifest file found at .\AndroidManifest.xml.
Falling back to the Android OS resources only. To remove this warning, annotate
your test class with #Config(manifest=Config.NONE).
No such manifest file: .\AndroidManifest.xml
I've tried these solutions that failed:
#Config (manifest = Config.DEFAULT_MANIFEST_NAME)
#Config(manifest = Config.NONE, constants = BuildConfig.class, sdk = 26)
#Config( constants = BuildConfig.class, manifest="src/main/AndroidManifest.xml", sdk = 26 )
And the other error during execution is:
android.content.res.Resources$NotFoundException: Unable to find
resource ID #0x7f09001b in packages [android, org.robolectric.default]
...
at
com.example.robertoassad.alltestsmerge.MainActivity.onCreate(MainActivity.java:52)
This line that have the error is the following code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Specifically in: setContentView(R.layout.activity_main);
For me I didn't see sense in this issue ...
DETAILS:
The test class is on the folder: app\src\test\java\com\example\robertoassad
The test is:
#RunWith( RobolectricTestRunner.class)
public class Roboletric {
#Test
public void clickingLogin_shouldStartLoginActivity() {
MainActivity activity = Robolectric.setupActivity(MainActivity.class);
activity.findViewById(R.id.button2).performClick();
Intent expectedIntent = new Intent(activity, SecondActivity.class);
Intent actual = ShadowApplication.getInstance().getNextStartedActivity();
assertEquals(expectedIntent.getComponent(), actual.getComponent());
}
}
I had a similar problem to the one you face. The post by jongerrish on the Robolectric GitHub Issue about this resolved the problem for me.
The aspect of the answer that worked for me was to add a testOptions block in my module's build.gradle file:
testOptions {
unitTests {
includeAndroidResources = true
}
}
After adding this block my tests were able to run and access String resources.
This problem bug me for some time, and here is my note in my test code.
About manifest location
With Gradle build system, Robolectric looks for AndroidManifest.xml in the following order.
Java resource folder
build/intermediates/manifests/[full or fast-start]/[build-type]
So it is a common mistake to specify the location of AndroidManifest.xml according to source code folder organization (e.g. src/main/AndroidManifest.xml) . The specified AndroidManifest.xml location affect how Robolectric look for merged resources as well. So if some resource is not found in test, it is probably due to incorrect setting of AndroidManifest.xml location.
That said, the Android Gradle plugin merge the AndroidManifest.xml and put the result under the above mentioned intermediates directory. So the content of src/main/AndroidManifest.xml affect the test result.
So if you want to specify manifest option in #Config, just use #Config(manifest=“AndroidManifest.xml”) should probably be fine. If you want to use an alternate AndroidManifest.xml, put it in Java resources folder, and specify #Config according to the relative path in resources folder.
I was also facing same problem while testing my library module from app. Now my Receievers and Service are in my library, so to test those , i had to implement custom Test Class, so Roboelectric can point to my library manifest and not the app manifest :
import android.os.Build;
import org.junit.runners.model.InitializationError;
import org.robolectric.manifest.AndroidManifest;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.res.Fs;
import java.io.File;
import java.io.IOException;
public class RobolectricGradleTestRunner extends RobolectricTestRunner {
private static final String PROJECT_DIR =
"C:/MyProject/";
private static final int MAX_SDK_SUPPORTED_BY_ROBOLECTRIC =
Build.VERSION_CODES.JELLY_BEAN_MR2;
public RobolectricGradleTestRunner(final Class<?> testClass) throws Exception {
super(testClass);
}
private static AndroidManifest getAndroidManifest() {
String manifestPath = PROJECT_DIR+"/src/main/AndroidManifest.xml";
String resPath = PROJECT_DIR+"/src/main/res";
String assetPath = PROJECT_DIR+"/src/main/assets";
System.out.print("manifest path: "+manifestPath);
System.out.print("resPath path: "+resPath);
System.out.print("assetPath path: "+assetPath);
return new AndroidManifest(
Fs.fileFromPath(manifestPath), Fs.fileFromPath(resPath), Fs.fileFromPath(assetPath)) {
#Override public int getTargetSdkVersion() {
return MAX_SDK_SUPPORTED_BY_ROBOLECTRIC;
}
};
}
private static String getProjectDirectory() {
String path = "";
try {
File file = new File("..");
path = file.getCanonicalPath();
path = path + "/app/";
} catch (IOException ex) {}
return path;
}
#Override public AndroidManifest getAppManifest(Config config) {
return getAndroidManifest();
}
}
and use it in your test class like :
#RunWith(RobolectricGradleTestRunner.class)
public class MyClassChangeTest {
}
I have three Android projects: BaseLibProject, MainLibProject, AppProject.
The relationship of these three Android projects is that:
The BaseLibProject is a library project used by MainLibProject.
The MainLibProject uses BaseLibProject as library project, and generates MainLib.jar(use maven build)
The generated MainLib.jar is added to AppProject's libs/ folder & also added to the build path of AppProject.
NEXT:
A simple class in BaseLibProject :
public class BaseLibClass {
public static String doBaseTask() {
Log.i("MyLog", "doBaseTask..."); //I can't see this log
return "Result from Base!";
}
}
A simple class in MainLibProject which defined a function invokes the function in BaseLibProject:
public class MainLibClass {
public static void doMainTask() {
Log.i("MyLog", "doMainTask..."); //I can see this log in logcat
String result = BaseLibClass.doBaseTask();
Log.i("MyLog", "result = " + result); //I can see the result log
}
}
Finally, in my AppProject I simply call above function of MainLibProject (remember I have MainLib.jar):
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MainLibClass.doMainTask();
}
}
I started logcat with command adb logcat -s MyLog:* . When I run my AppProject application, logcat displays
I/MyLog(2039): doMainTask...
I/MyLog(2039): result = Result from Base!
According to above log, the code in BaseLibProject is running (because I got result from BaseLibClass), but it doesn't display any logs from BaseLibProject, why???
(I have googled on internect, someone got similar issue fixed by restarting eclipse, but in my case, it doesn't help. Besides, I am checking logs from terminal NOT from eclipse.)
Ok, finally, I fixed the problem.
The reason is that in BaseLibProject pom.xml, I defined <packaging>apk</packaging>, while in MainLibProject pom.xml, when I define the dependency of BaseLibProject, I didn't specify the <type> of the artifact.
After I changed BaseLibProject's pom.xml to <packagin>apklib</packaging> and in MainLibProject's pom.xml specified the dependency of BaseLibProject with <type>apklib</type> . I am able to see the logs in BaseLibProject.
I followed the exact steps given in the post below:
Is it possible to dynamically load a library at runtime from an Android application?
I am using and android 2.2 phone for testing and getting an error which is driving me crazy :(
07-27 01:24:55.692: W/System.err(14319): java.lang.ClassNotFoundException: com.shoaib.AndroidCCL.MyClass in loader dalvik.system.DexClassLoader#43abbc20
Can someone help me what to do now..i have tried various suggested solutions on different posts
I was wondering whether this was feasible so I wrote the following class:
package org.shoaib.androidccl;
import android.util.Log;
public class MyClass {
public MyClass() {
Log.d(MyClass.class.getName(), "MyClass: constructor called.");
}
public void doSomething() {
Log.d(MyClass.class.getName(), "MyClass: doSomething() called.");
}
}
And I packaged it in a DEX file that I saved on my device's SD card as /sdcard/testdex.jar.
Then I wrote the program below, after having removed MyClass from my Eclipse project and cleaned it:
public class Main extends Activity {
#SuppressWarnings("unchecked")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
final String libPath = Environment.getExternalStorageDirectory() + "/testdex.jar";
final File tmpDir = getDir("dex", 0);
final DexClassLoader classloader = new DexClassLoader(libPath, tmpDir.getAbsolutePath(), null, this.getClass().getClassLoader());
final Class<Object> classToLoad = (Class<Object>) classloader.loadClass("org.shoaib.androidccl.MyClass");
final Object myInstance = classToLoad.newInstance();
final Method doSomething = classToLoad.getMethod("doSomething");
doSomething.invoke(myInstance);
} catch (Exception e) {
e.printStackTrace();
}
}
}
I guess your problem lies on the way you package MyClass in a DEX. How do you do that?
I followed Shlublu's thread and tried myself and succeeded. I don't know how to "package MyClass in a DEX", so I simply build an android apk and put it in the sdcard. And the code worked.
Are you wraping MyClass in a classes.dex? DexClassLoader will only look for classes.dex in your jar/dex. Maybe you can first try what I did (build an signed apk instead of jar, but you don't need to install the apk), and see if it's working. Hope this helps!
I have a problem with my code which refuses to go away. This is the first half of my code:
public class SampleGame extends AndroidGame {
public static String map;
boolean firstTimeCreate = true;
#Override
public Screen getInitScreen() {
if (firstTimeCreate) {
Assets.load(this);
firstTimeCreate = false;
}
InputStream is = getResources().openRawResource(R.raw.map1);
map = convertStreamToString(is);
return new SplashLoadingScreen(this);
}
An error message is generated on the line
InputStream is = getResources().openRawResource(R.raw.map1)
The error message says I should add the line "import android.R", but when I do this, a second error message is generated which says "map1 cannot be resolved or is not a field." Can someone please give me any suggestions on how to solve this intractable problem?
Be sure that there is map1 in Raw folder.If it exists,then try clean/build your project or close and reopen eclipse.It may be solved.
Try updating your Eclipse android ADT to the latest, restart it.
Im not very good at android but if yours does have an onCreate some where make sure u reference your Resources after it has done the onCreate stuff.
This may be a simple answer.
1) Create a jar file with this code:
package com.myCompany.base;
public class Dex1 {
public String getTerm1() {
return "Term 1";
}
}
This is compiled to Dex1.jar using NetBeans.
2) Created a 'Hello world' android application in Eclipse. Add the code for Dex2 that extends Dex1. Copy and add Dex1.jar to the java build path.
package com.myCompany;
import com.myCompany.base.Dex1;
public class Dex2 extends Dex1 {
public String getTerm2() {
return getTerm1() + " Term 2";
}
}
in my onCreate() call:
editText.setText(dex2.getTerm2());
Everything works Great! I get the correct string displayed on the android screen. Yea!
Now the problem starts:
3) Create a jUnit 3 test case using Eclipse command File -> New -> Project -> Android Text Project command and add the code:
package com.myCompany.test;
import junit.framework.TestCase;
import com.myCompany.Dex2;
public class Dex2Test extends TestCase {
protected void setUp() throws Exception {
super.setUp();
dex2 = new Dex2();
}
protected void tearDown() throws Exception {
super.tearDown();
}
Dex2 dex2;
public void testGetTerm2() {
/*line 21 */ assertEquals("Term 1 Term 2", dex2.getTerm2());
}
public void testGetTerm1() {
/* line 25 */ assertEquals("Term 1", dex2.getTerm1());
}
}
On Line 25 the compiler gives a 'method undefined' error for getTerm1(). I don't understand why this is an error?
I tried to add the Dex1.jar to the java Build path of the test project, it compiles but we receive a run time error 'NoClassDefFoundError'. Yuch!
More Information 16Mar2012
I set this up using Plan Java classes, same jar file, to remove Android and it worked. This makes me conclude there must be some anomaly in Android/DalvikVM (aka DavrosVM).
More Information 16Mar2012 End
Am I missing something?
Is the jar file built incorrectly (didn't think that was possible)?
Am I importing the jar file incorrectly?
Is it just crazy to expect to import and override a class in a jar file?
Thank you for reading, please reply.
Fish
Take a look at Android Testing: External libraries which I guess have the solution to your problem.
What you may be doing wrong is not exporting your library in Order and Export under Java Build Path.