Extend abstract IntentService from Library result on Intent not found - android

I'm building a library that I use then on my application. The idea is that the library has an Abstract class that extends from IntentService so that the app can create a subclass of this Service and manage the information there.
The problem is that I have declared MyIntentService that extends from the IntentService of the library, declared on the manifest but when I start to run it within the library the service can't be found.
Makes sense that is not found as from the library I don't know the new class I just try to open the one that is abstract from the library.
Any help is welcome, I'm a bit lost.
Library -> Abstract IntentService
public abstract class NotificationReceiver extends IntentService {
public NotificationReceiver() {
super("NotificationReceiver");
}
public final void onHandleIntent(Intent intent) {
L.d("NotificationReceiver","onHandleIntent","NEW MESSAGE");
this.notificationReceived();
}
public abstract void notificationReceived();}
This does not get declared inside the manifest as it's abstract
App -> IntentService that extends the one from the library
public class MyNotificationHandler extends NotificationReceiver {
public MyNotificationHandler() {
super();
}
public MyNotificationHandler(String name) {
super();
}
#Override
public void notificationReceived() {
Log.d("MyNotificationHandler","NEW NOTIFICATION TO DISPLAY");
}}
This is declared in the manifest of the application:
<!-- NOTIFICATIONS -->
<service android:name="com.test.demosdk.MyNotificationHandler" >
</service>
And the IntentService gets started from the library using this:
Intent generalIntent = new Intent(DemoSDKManager.getApplicationContext(),NotificationReceiver.class);
startService(generalIntent);
The above results on an IntentService not found.

Related

Is it possible to write into an external library on android studio

I want to add a function into my firebase-messaging librady.The file is not writable.Is it possible somehow to write in it?
No, you can't do that. If you want to add a method to FirebaseMessagingService, make an abstract class that extends FirebaseMessagingService and extend that class in your implementations.
public abstract class BaseMessagingService extends FirebaseMessagingService {
public void yourMethod() {
}
}
public class YourActualMessagingService extends BaseMessagingService {
//...
}

Cannot cast Application to CustomApplication

I have a CustomApplication extends Application class, which is registered in AndroidManifest
<application
....
// Please, pay attention that I got this in my Manifest
android:name=".CustomApplication">
And at different part of my application, both some activities and services I do
getApplication()/getApplicationContext() then cast it to CustomApplication and it crashes in production on a variety of devices/sdk versions(beginning at android 6) due to a class cast exception. Caused by: java.lang.ClassCastException
Example:
class CustomApplication extends Application{
...
public static CustomApplication with(Context context) {
return (CustomApplication) context.getApplicationContext(); //crashes here
}
}
and service example:
class CustomService extends IntentService{
...
#Override
rotected void onHandleIntent(#Nullable Intent intent) {
CustomApplication app = CustomApplication.from(getApplication());
// tried getApplicationContext() also
}
}
and activity example:
class CustomActivity extends AppCompatActivity{
...
#Override
protected void onCreate(...){
CustomApplication app = CustomApplication.with(this);
}
What I've tried:
Tried services with different process=":process"
Tried deep linking with different launchModes
Tried activities with taskAffinity
launching from push notifications
process cleaning with system tray(on device), ps kill int adb shell
nothing helps me to reproduce an issue on emulator
I don't use Instant Run also (never used it)
Please don't provide me with suggests of using static application context instance
You can keep a static reference of your CustomApplication like below. You don't need to cast in the following way.
public class CustomApplication extends Application {
private static CustomApplication instance;
#Override
public void onCreate() {
super.onCreate();
instance = this;
}
public static CustomApplication getContext() {
return instance;
}
}
Then call CustomApplication.getContext();
You need to define your custom application in the manifest as follow:
<application
....
android:name="my.package.path.CustomApplication">
... activities ....
</application>
Also, you are getting an instance of a class that extends Application, not Context, that being said you should call this the following way:
CustomApplication customApplication;
customApplication = (CustomApplication)getApplication();
What you might have to apply in case you have BroadcastReceiver(No context available) is:
customApplication = (CustomApplication)getApplicationContext().getApplication();

How to inject a bound service into an Activity via dagger?

I would like to inject a bound service into my activity via Dagger2.
My Service is declared as follow:
Public class MyService extends Service{
private final IBinder mBinder = new LocalBinder();
...
public class LocalBinder extends Binder {
public MyService getService() {
return MyService.this;
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public void doBackgroundTask() {
...
}
}
My Activity:
public abstract class MainActivity extends AppCompatActivity {
#Inject
MyService service;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
service.doBackgroundTask();
...
}
How would you achieve that ? Where will you put the ServiceConnection (into a base class, inside the module) ?
Thanks a lot.
I don't think that injecting the service that way (via injected field) will work because you don't control the instantiation of the service's object.
If your service contains fields that need to be injected you will have to inject in onCreate() the same way you inject your activities, i.e. calling DaggerMyAppComponent.inject(this).
About the ServiceConnection: you will have to do it the usual way as described in http://developer.android.com/guide/components/bound-services.html
I was dealing with the same concept/problem and like #Ognyan says - you won't have control over creating service.
I think this: How to access service functions from fragment, which is bound to parent activity in Android? might help you.
You may instantiate service in Application/Activity and communicate with it as described in the attached link.
You may also think of putting the interface (which is communicating with service) in base abstract class (BaseActivity or BaseFragment) which Fragment/Activity inherits and then easily reach the interface in any fragment or activity you need.
Hope it solves your issue.

Adding Test Module for RoboGuice When Using Robolectric 2

I am currently upgrading robolectric from version 1 to 2. In my current version I use the following to provide the test module (for binding) to roboguice.
public class RoboTestRunner extends RobolectricTestRunner {
public RoboTestRunner(Class<?> testClass) throws
InitializationError {
super(testClass);
}
#Override
public void prepareTest(Object test) {
Application app = Robolectric.application;
RoboGuice.setBaseApplicationInjector(app, RoboGuice.DEFAULT_STAGE,
Modules.override(RoboGuice.newDefaultRoboModule(app)).with(new
TestModule()));
Injector injector = RoboGuice.getInjector(app);
injector.injectMembers(test);
}
}
However now I have upgraded the prepareTest method is not in this class. Where should I run this code in the new version?
UPDATE
I have found the way to do this. I need to create an class which extends android.app.Application in the project and reference this in the Manifest. Then I create a class like so
public class TestApplication extends Application implements TestLifecycleApplication {
#Override
public void onCreate() {
super.onCreate();
RoboGuice.setBaseApplicationInjector(this, RoboGuice.DEFAULT_STAGE,
RoboGuice.newDefaultRoboModule(this), new TestModule());
}
#Override
public void beforeTest(Method method) {}
#Override
public void prepareTest(Object test) {
TestApplication application = (TestApplication) Robolectric.application;
RoboGuice.setBaseApplicationInjector(application, RoboGuice.DEFAULT_STAGE,
RoboGuice.newDefaultRoboModule(application), new TestModule());
RoboGuice.getInjector(application).injectMembers(test);
}
#Override
public void afterTest(Method method) {}
}
As this class has Test at the start robolectric should automatically find it and use it. However this doesn't seem to be happening. Does anybody know why?
UPDATE 2
This blog would suggest that the testmodule needs to be in the same package however I have all tests in a different package. How do I work around this?
Your TestApplication class should extend your own Application class, not android.app.Application, and it should be in the same package as your Application.
... however I have all tests in a different package.
That shouldn't be a problem. Put your TestApplication in your test module, but use the package from Application.
e.g., if you're using maven, the files would live here:
src/main/java/com/example/Application.java
src/test/java/com/example/TestApplication.java

How to call an Abstract Class extending Service or a Thread in the Main Activity?

I'm trying to create an abstract class that extends either a service or a thread. This is because i must run this class every second to find out the foreground activity. If its Service i'm using Runnable and make it run every second using Handler. But I'm unable to Start the service or thread from the main activity. I know that abstract classes cant be instantiated but is there any work around that i could use over here?? Please, help.
public abstract class A extends Service Implements Interface {
public void onCreate() {
super.onCreate();
mHandler.postDelayed(runnable, 1 * 1000);
}
protected abstract void getData();
public Runnable runnable = new Runnable() {
public void run() {
//Trying to find Foreground Activities
A start = new B();
start.getData();
mHandler.postDelayed(runnable, 1 * 1000);
}
};
//Inteface methods defined here.
}
Another class:
public class B extends A {
public void getData() {
//Do my stuff
}
}
Now I need to call this A class, so that this abstract method can be executed in which ever class I extend A.
To instantiate an abstract class('s anonymous subclass):
abstract class AbstractClass {}
public class MyActivity extends Activity {
public void onCreate(Bundle i) {
AbstractClass abstractInstance = new AbstractClass(){};
}
}
Though actually you are not supposed to need to do this. What I would suggest is a simple JavaSE concurrency based approach, using ScheduledExecutorService.

Categories

Resources