Apache Felix - Using a bundle service shows "java.lang.ClassCastException" - android

I am embedding Apache Felix into an Android application. In that application, I am trying to use a service provided by a bundle. The bundle is successfully installed and started, but at the line that uses the service which is:
System.out.println( ((AndroidService) services [0]).startActivity());
I get the following error:
java.lang.ClassCastException: androidapi_bundle.AndroidServiceImpl cannot be cast to com.example.android_services.AndroidService
I have the following in my bundle:
1- Activator class
package androidapi_bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import com.example.android_services.AndroidService;
import android.util.Log;
public class Activator implements BundleActivator {
private static BundleContext context;
static BundleContext getContext() {
return context;
}
public void start(BundleContext bundleContext) throws Exception {
Activator.context = bundleContext;
System.out.println("This is a java message inside the start method of AndroidAPI_Bundle");
Log.d("Zitona Log","This is android message inside the start method of AndroidAPI_Bundle");
context.registerService(
AndroidService.class.getName(), new AndroidServiceImpl(),null);
}
public void stop(BundleContext bundleContext) throws Exception {
Activator.context = null;
Log.d("Zitona Log","AndroidAPI_Bundle stopped!");
}
}
2- com.example.android_services which has AndroidService.java interface:
package com.example.android_services;
public interface AndroidService {
public String startActivity();
}
3- its implementation class AndroidServiceImpl.java :
package androidapi_bundle;
import com.example.android_services.*;
public class AndroidServiceImpl implements AndroidService {
#Override
public String startActivity()
{
return "Activity started";
}
}
Now, in my android app I also have AndroidService.java interface, and the following is the code that uses the service:
#SuppressWarnings({ "rawtypes", "unchecked" })
ServiceTracker m_tracker = new ServiceTracker(
m_activator.getContext(),AndroidService.class.getName(), null);
m_tracker.open();
System.out.println("8");
Object[] services = m_tracker.getServices();
System.out.println("9");
System.out.println( ((AndroidService) services [0]).startActivity());
System.out.println("10");
After "9" is displayed I get the error. Where did I go wrong?
Below is my bundle MANIFEST:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: AndroidAPI_Bundle
Bundle-SymbolicName: AndroidAPI_Bundle
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: androidapi_bundle.Activator
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: org.osgi.framework;version="1.3.0", android.util, com.example.android_services
Export-Package: com.example.android_services
Update:
I realized that I have this line of code:
m_configMap.put(FelixConstants.FRAMEWORK_SYSTEMCAPABILITIES_EXTRA, "com.example.android_services");
so I changed it to:
m_configMap.put(FelixConstants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, "com.example.android_services");
Now I am getting this error:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.apache_felix_android/com.example.apache_felix_android.MainActivity}: java.lang.NullPointerException

The only way you can get this is if both the activator bundle and the app bundle have an internal copy of the service class and neither exports it. So you will need to show your manifests and bundle contents.
Update What on earth are you mucking with advanced options like system packages (and then using Felix classes instead of OSGi's constant class) when you seem to have very basic problems. Why not start with a clean simple bndtools, make your app work in there using an IDE, and then when it works port it to Android? This all looks awfully masochistic way to learn OSGi?

Related

Using native Android view in ReactNative: Constructor ReactImageView in class ReactImageView cannot be applied to given types

Attempting to create an Android view to use in ReactNative later on.
This is the code that I wrote following the official tutorial, but I'm still getting some troubles compiling.
Here is the error message that I get:
Error:(15, 53) error: constructor ReactImageView in class ReactImageView cannot be applied to given types;
required: Context,AbstractDraweeControllerBuilder,GlobalImageLoadListener,Object
found: no arguments
reason: actual and formal argument lists differ in length
Here instead is the code:
package com.androidbridge;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.views.image.ReactImageView;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.drawee.backends.pipeline.Fresco;
import javax.annotation.Nullable;
public class ReactImageManager extends SimpleViewManager<ReactImageView> {
public static final String REACT_CLASS = "RCTImageView";
private Object mCallerContext;
public ReactImageManager(Object mCallerContext) {
this.mCallerContext = mCallerContext;
}
#Override
public String getName() {
return REACT_CLASS;
}
#Override
protected ReactImageView createViewInstance(ThemedReactContext reactContext) {
return new ReactImageView(reactContext, Fresco.newDraweeControllerBuilder(), mCallerContext);
}
}
I am kind of lost as the code is derived from the official tutorial.
It seems like the signature of the class ReactImageView has changed since the tutorial was written, the constructor now also require you to pass an object of type GlobalImageLoadListener. It is marked as nullable as of the latest react-native version, so you can try just passing a null reference.
I just got started myself and find the tutorial somewhat lacking.

Error:(42, 16) error: incompatible types required: Loader<List<String>> found:FileLoader

I'm trying to use the LoaderManager in my code however I'm getting an incompatible types error:
#Override
public Loader<List<String>> onCreateLoader(int id, Bundle args) {
return new FileLoader(MainActivity.this);
}
shouldn't this statement return new FileLoader(MainActivity.this) returns a Loader? And here is the implementation of the LoaderManager:
public class FileLoader extends AsyncTaskLoader<List<String>>{
public FileLoader(Context context){
super(context);
}
#Override
public List<String> loadInBackground() {
.........
........
return listFiles;
}
}
I had the same problem(incompatible types required), but when see your post ,it helps me to learn more.In my code, it was imported:
"import androidx.loader.content.AsyncTaskLoader;"
, so i change it to:
"import android.content.AsyncTaskLoader;"
then my problem solved.
Because "AsyncTaskLoader" : This class was deprecated in API level 28,by below ref.
https://developer.android.com/reference/android/content/AsyncTaskLoader
by this advice,"You should also consider migrating existing projects to AndroidX", the webpage below:
https://developer.android.com/jetpack/androidx/migrate/class-mappings
finally I succeeded to solve the problem ... it was that didn't Import the support library in the AsyncTaskLoader file , while using it at the Main file ...so i just removed
import android.content.AsyncTaskLoader;
and Import the following support library
import android.support.v4.content.AsyncTaskLoader;

Android - How to UnitTest a Logging class with mockito

I have written a class to manage logging within an android application project.
The LogManager is basically a wrapper for android.util.log
It handles logging to a file, if the application crashes, and standard debug logging.
I would like to unit test the class using JUnit.
I have tried the following but it does not seem to produce the results I would expect after reading the examples:
LogManager.class (This is a simplified version of the class I have used, for demonstration purposes)
public class LogManager implements ILogManager
{
public void log(String tag, String message)
{
Log.e(tag, message);
}
}
And here is my test class
#RunWith(RobolectricGradleTestRunner.class)
#Config(constants = BuildConfig.class, sdk = 21)
#PrepareForTest({Log.class, LogManager.class})
public class LogManagerUnitTest
{
#Test
public void testLogConsoleInfo()
{
PowerMockito.mockStatic(Log.class);
LogManager.getInstance().log(LogLevel.INFO, "test", "test");
PowerMockito.verifyStatic(Mockito.times(1));
Log.e(anyString(), anyString());
}
}
My problem is that this passes no matter what I put.
E.g: if I instead replace the last call with Log.wtf(...) it still passes. I would have assumed that it should fail since Log.wtf was not called in the static class Log?
So my question is, why isn't this approach working as expected and what would be the correct way to do it?
I started a fresh project and was able to get it to fail tests and succeed appropriately using the following, so I'm assuming the runwith was the culprit:
#RunWith(PowerMockRunner.class)
#PrepareForTest(android.util.Log.class)
public class LoggerUnitTest {
#Test
public void testLog() throws Exception
{
PowerMockito.mockStatic(Log.class); // when(Log.e(anyString(), anyString())).thenReturn(1);
Logger.log("test", "test");
PowerMockito.verifyStatic(times(1));
Log.e(anyString(), anyString());
} }
For the RobolectricGradleTestRunner, the following incantation would have exposed your logging:
ShadowLog.stream = System.out
Robolectric does not print the Android system logging by default.
It's also worth noting that the RobolectricGradleTestRunner has been deprecated in favor of the fully operational RobolectricTestRunner (The above assignment is still effective)

Android Eclipse jUnit does not see superclass

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.

Android app unit testing

So, I'm new to android unit testing. I'm trying to write a unit test for the Phone application:
package com.android.phone;
import android.content.Intent;
import android.net.Uri;
import android.test.ApplicationTestCase;
import android.test.suitebuilder.annotation.MediumTest;
import com.android.phone.PhoneApp;
import dalvik.annotation.TestTargetClass;
#TestTargetClass(PhoneApp.class)
public class TestPhone extends ApplicationTestCase<PhoneApp> {
public TestPhone() {
super(PhoneApp.class);
}
private PhoneApp phone;
#Override
protected void setUp() throws Exception {
super.setUp();
phone = getApplication();
}
#MediumTest
public void testDialerIsUp() {
assertNotNull("Phone app does not exist", phone);
// TODO add tests
}
}
Then I start an emulator, wait till it boots up, and run those tests:
adb shell am instrument -e class com.android.phone.TestPhone -r -w com.android.phone.tests/android.test.InstrumentationTestRunner
And now I'm getting a junit.framework.AssertionFailedError: PhoneApp does not exist. What is wrong here, why isn't PhoneApp up?
Actually, I'd recommend calling createApplication() in your setUp() method before calling phone = getApplication().
You don't show the code for your PhoneApp. Did you derive a PhoneApp class from the android.app.Application class? Or are you expecting that there is just something called PhoneApp out there that you can test?
You will need to write an android.app.Application class as part of your project, if you expect to test something.
Or, perhaps, you are talking about something that I do not understand. That is always possible.
How does this even compile with "PhoneApp.class" in it if you just stick to the SDK?
I know you can use Robotium to test existing apps though.
Elaborating on Karim's answer (it does work), this is the setup method:
MyApplication application;
#Override
protected void setUp() throws Exception {
super.setUp();
createApplication();
application = getApplication();
}

Categories

Resources