I tried to access NotificationManagerService class which is in android.service.notification package using reflection method. I tried this to clear Notifications of other apps which has FLAG_NO_CLEAR
Here is the snippet,
try {
Class<?> c = Class.forName("com.android.server.notification.NotificationManagerService");
Constructor<?> constructor = c.getDeclaredConstructor();
constructor.setAccessible(true);
Object o = constructor.newInstance();
Method method = c.getDeclaredMethod("cancelAllNotificationsInt",
new Class[]{String.class,int.class,int.class,boolean.class});
method.setAccessible(true);
Object r = method.invoke(o,sbn.getPackageName(), Notification.FLAG_NO_CLEAR,0,true);
if((boolean)r)
Log.d("Working","yes");
} catch (Exception e) {
e.printStackTrace();
}
But I am getting exception,
java.lang.ClassNotFoundException:
com.android.server.notification.NotificationManagerService
The class exist and here is the link from where I confirmed it.
Help me!!! Thanks in advance
Using Reflection and trying to assess Framework class is not a good way of implementing a feature. This is a bad practice.
From Android 4.3 onward, you can now cancel notifications from any apps.
You just need to implement the NotificationListenerService
you could cancel the notification of any app using the method NotificationListenerService.cancelNotification(String pkg, String tag, int id)
you could refer this sample notification-listener-service-example
I am not very particular with android development but this is usually environment issue. Sometimes, the actual class is not there in the library depending on how you have included your dependencies.
If at your development / IDE, you already encounter the problem, go to your external libraries imported by your gradle (or maven). Drill down to com.android.server.notification.NotificationManagerService if it is there. Or debug it and see if Class<?> c is null.
If it happened on the deployed version, open the file, go to the imported classes and drill down to the actual class if it is there or not.
If this library is provided by the environment you deploy - might be (1) overwritten by other library conflict or (2) version issue
Related
Is that possible implement the same code but only enabled when adding a dependency to SpringBoot project?
If possible, how to achieve it?
I want to implement the code like this:
DoSomethingUtil doSomethingUtil = new DoSomethingUtil();
doSomethingUtil.send("API URL", "System A", "Hello");
It would do nothing when project didn't add the implement of the DoSomethingUtil.java.
After adding to pom.xml that which would implement the DoSomethingUtil.java, it would really do something.
Given that you don't need to know about DoSomethingUtil anywhere else in your code, you can run something on it only if it's present in your classpath (without importing it) if you use reflection all the way:
try {
Class<?> dsuClass = Class.forName("do.something.util.DoSomethingUtil");
Object dsuInstance = dsyClass.getConstructor().newInstance();
Method sendMethod = dsuClass.getDecaredMethod("send", String.class, String.class, String.class);
sendMethod.invoke(dsuInstance, "API URL", "System A", "Hello");
} catch (Exception ignored) {}
You may want to revisit the poor error handling above to distinguish (at least) between class not being present in the classpath and send() method invocation failure.
What you appear to be describing is adding a dependency, not "importing" something.
Will it work?
Sort of. What you could do is overlay the definition of the.pkg.DoSomethingUtil with another version of the.pkg.DoSomethingUtil in a different JAR file. It can work, but it makes your application sensitive to the order of the JARs on the runtime classpath. That makes your application fragile ... to say the least.
You can probably make this work with classic Java if you have full control of the runtime classpath. However:
I'm not sure if it will work with SpringBoot.
If you tried this sort of thing on Android, the APK builder would protest. It treats the scenario of two classes with the same full name as an error.
I think there is a better solution:
Refactor the code so that there is a DoSomethingUtil interface and two classes; e.g. RealDoSomethingUtil and DummyDoSomethingUtil.
Replace new DoSomethingUtil() with a call to a factory method.
Implement the factory method something like this:
private static Class<?> doSomethingClass;
public static synchronized DoSomethingUtil makeDoSomethingUtil() {
if (doSomethingClass == null) {
try {
doSomethingClass = Class.forName("the.pkg.RealDoSomethingUtil");
} catch (Exception ex) {
doSomethingClass = the.pkg.DummyDoSomethingUtil.class;
}
}
return (DoSomethingUtil) (doSomethingClass.newInstance());
}
Put RealDoSomethingUtil into the add-on JAR file, and DoSomethingUtil, RealDoSomethingUtil and the factory method into the main JAR file.
You should probably make the exception handling more selective so that it deals with different classloader errors differently. For example, if RealDoSomethingUtil exists but can't be loaded, you probably should log that ... or maybe let the exception crash the application.
You could also make use of ServiceLoader, but I don't know if it would be simpler ...
The java Service Provide API (SPI) is there to detect wether implementation(s) of an interface exists.
You have a jar with an interface DoSomethingUtil in your application.
Possibly on the class path an implementation jar (MyDoSomethingUtilImpl implements DoSomethingUtil), with an entry in META-INF/services.
You must check whether the interface is implemented.
One could make a fallback implementation.
ClassLoader classLoader = QuarkusClassLoader.getSystemClassLoader();
String str = "com.mycompany.service.SomeClass";
try {
Class<? extends SomeClass> someClass =
(Class<? extends SomeClass>) classLoader.loadClass(str);
} catch (Throwable e) {
e.printStackTrace();
}
I'm trying to figure out why I get java.lang.ClassNotFoundException when I try to load com.mycompany.service.SomeClass. This class is defined locally in the project, I'm getting this error when I start my Quarkus app (mvn compile quarkus:dev). If I use another class loader (i.e. this.getClass().getClassLoader()), this error does not happen. It seems like it only happens with QuarkusClassLoader
EDIT:
I think in the end the problem was related to Debezium Engine initialisation. That exception was thrown when calling the following line:
// Create the engine with this configuration ...
engine =
DebeziumEngine.create(Json.class)
.using(props)
.notifying(this::handleDbChangeEvent)
.build();
See my answer for how I fixed it
Using Classloader.getSystemClassLoader is certainly not the correct thing to do because in dev-mode (and more generally, you would rarely want to do that in Java code), Quarkus dot not a flat classloader structure, but a layered one.
See https://quarkus.io/guides/class-loading-reference for more details on how Classloading in dev-mode works.
You can force all classes of a jar to be loaded by the system ClassLoader instead of the Quarkus ClassLoader by using something like:
quarkus.class-loading.parent-first-artifacts=stax:stax-api
Where you essentially configure the groupId and the artifactId of the jar that should be loaded by the system ClassLoader
I fixed this by passing Thread.currentThread().getContextClassLoader() in the engine initialisation.
engine =
DebeziumEngine.create(Json.class)
// Have to pass the current class loader to avoid ClassNotFoundException
.using(Thread.currentThread().getContextClassLoader())
.using(props)
.notifying(this::handleDbChangeEvent)
.build();
I'm developing a Java ME project in Intellij. When I try to call a function from the javax.microedition package, all functions simply return null. After inspection, these functions exist but contain no substance (are unimplemented). For example, the javax.microedition.io.connector class function .open(String var) appears this way and always returns null:
public static Connection open(String var0) throws IOException {
return null;
}
This function does not match the documentation provided by Oracle and according to the documentation Connector is not an abstract class. All other functions I inspected seem to be implemented the same way. Did I miss a step in setting up the Java ME SDK? Am I missing something?
Additionally this is the code I try to run but returns null:
ServerSocketConnection server = (ServerSocketConnection) Connector.open("socket://:4040");
These are called stub classes. They only contain method signatures and default return values. You can use them to compile your code without problems.
When you run your app on an emulator (or on an actual device) these classes will have a proper implementation and behave as expected.
I am trying to integrate my GWT code with Guice/GIN (as it needs different config on the client, in the JVM (shared code), and when running tests). I am now getting a strange error about not finding a method when compiling:
[INFO] com.google.gwt.dev.jjs.InternalCompilerException: Unexpected error during visit.
...
[INFO] Caused by: java.lang.UnsatisfiedLinkError: com.google.gwt.user.client.Timer.createCallback(Lcom/google/gwt/user/client/Timer;I)Lcom/google/gwt/core/client/JavaScriptObject;
[INFO] at com.google.gwt.user.client.Timer.createCallback(Native Method)
[INFO] at com.google.gwt.user.client.Timer.scheduleRepeating(Timer.java:121)
[INFO] at ...
com.google.gwt.user.client.Timer resides in the User module, and Timer.scheduleRepeating() is written in Java, and delegates to Timer.createCallback(), which is a "native" (JavaScript) method. So the compiler finds Timer itself, and Timer.scheduleRepeating(), but not the native method.
What could cause this? I did not have this issue before trying to use GIN.
EDIT: Since others seem to see different code, here is what I see when looking at com.google.gwt.user.client.Timer:
...
private static native JavaScriptObject createCallback(Timer timer, int cancelCounter) /*-{
return $entry(function() { timer.#com.google.gwt.user.client.Timer::fire(I)(cancelCounter); });
}-*/;
...
public void scheduleRepeating(int periodMillis) {
if (periodMillis <= 0) {
throw new IllegalArgumentException("must be positive");
}
if (isRunning()) {
cancel();
}
isRepeating = true;
timerId = Impl.setInterval(createCallback(this, cancelCounter), periodMillis);
}
...
You have added a new dependencies in the project.
Please clean the project and re-compile it again.
Remove gwt-unitCache and other auto generated stubs also as shown in below screenshot
OK, I worked it out. In the GIN module, I am injecting some piece of code that needed to create a GWT Timer. And the problem was, that GIN execute the module at compile time. Of course, at compile time, the GWT Timer "native code" was not available, since that happened in the JVM itself.
So I just tried to catch the UnsatisfiedLinkError and ignore it. But that die not work out directly either, because UnsatisfiedLinkError is not available in GWT, so I just caught "Error" instead, and checked the class name. Then it all worked. But not before I discovered, to my dismay, that I cannot override a "provideXXX()" method on a GIN module (why?). Also, even if it is allowed for a GIN module to be abstract, GIN still requires a public no-arg constructor (which GIN will never call, because an abstract class cannot be instantiated!).
I'm attempting to implement a package-scanning feature, similar to Spring's component-scan, for the Android framework I'm developing. Basically, I would like to be able to specify a base package, e.g. com.foo.bar and retrieve all Class instances that have a particular annotation. I don't want to have to register every component with my framework as that would defeat the purpose of the auto scanning.
Based on my research, it seems that it's not possible with Java to retrieve resources given a package name using reflection. However, I briefly looked into the Reflections framework, and I'm wondering if there is an Android-compatible equivalent. If not, perhaps there is a slightly less obvious way to accomplish what I want to do.
I looked into the Spring source a bit to see how they achieved this, but I don't think what they are doing would work within the Dalvik runtime.
Update
Currently, the below code has been the best I can do to retrieve all classes that contain a specific annotation, but frankly it's a pretty poor solution. It makes some really unsafe assumptions about the ClassLoader plus it scans (and loads) all application classes.
public Set<Class<?>> getClassesWithAnnotation(Class<? extends Annotation> annotation) {
Set<Class<?>> classes = new HashSet<Class<?>>();
Field dexField = PathClassLoader.class.getDeclaredField("mDexs");
dexField.setAccessible(true);
PathClassLoader classLoader = (PathClassLoader) Thread.currentThread().getContextClassLoader();
DexFile[] dexs = (DexFile[]) dexField.get(classLoader);
for (DexFile dex : dexs) {
Enumeration<String> entries = dex.entries();
while (entries.hasMoreElements()) {
String entry = entries.nextElement();
Class<?> entryClass = dex.loadClass(entry, classLoader);
if (entryClass != null && entryClass.isAnnotationPresent(annotation)) {
classes.add(entryClass);
}
}
}
return classes;
}
I wanted to find all the subclass at runtime.
So I've been looking for android class scanning.
This is my final code from what I gathered in web.
You will get the idea.
public static void findSubClasses(Context context, Class parent) {
ApplicationInfo ai = context.getApplicationInfo();
String classPath = ai.sourceDir;
DexFile dex = null;
try {
dex = new DexFile(classPath);
Enumeration<String> apkClassNames = dex.entries();
while (apkClassNames.hasMoreElements()) {
String className = apkClassNames.nextElement();
try {
Class c = context.getClassLoader().loadClass(className);
if (parent.isAssignableFrom(c)) {
android.util.Log.i("nora", className);
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// android.util.Log.i("nora", className);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
dex.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I share the opinion of Joop Eggen and find his approach a good one. In Android I try to avoid the usual web app features which lead to a long lasting application start. I do not use reflection or package scanning.
But if you want to .... if I understand it correctly you want to have an annotation for a class. Instead of using annotations you could also use marker interfaces (to just have more possibilites).
1) Look at
Annotation: Java custom annotation and dynamic loading
Has an implementation in the question which just answers your question.
Annotation: Scanning Java annotations at runtime
Interface: Find Java classes implementing an interface
Interface: Is something similar to ServiceLoader in Java 1.5?
Interface: How can I get a list of all the implementations of an interface programmatically in Java?
Interface: Since the approach is expensive, maybe the ServiceLoader is a compromise between execution time and comfort, since it loads only the classes given in the services file. On the other hand if only classes with a certain interface are in your package then the ServiceLoader isn't that faster.
2) AndroidAnnotations
I would prefer the way AndroidAnnotations work (maybe an integration in AndroidAnnotations is the preferable way): It automatically adds an extra compilation step that generates source code, using the standard Java Annotation Processing Tool. So instead of runtime scanning you execute code based on the annotations generated during compile time.
I think the Bean/EBean annotation could work for you (only single class): https://github.com/excilys/androidannotations/wiki/Enhance%20custom%20classes
A scan-feature is not available, see this thread
3) Writing your own annotation processor
See APT (Annotation Processing Tool). The idea would be to generate a static function which returns a list of classes which are annotated, so that no class scanning is needed.
A very good ressource is http://javadude.com/articles/annotations/index.html
Take a look at Vogar's ClassPathScanner. It uses it to find test cases on the class path.
EDIT:
I found this issue in the Android issue tracker. It appears that ClassLoader.getResource(String) is 'working as expected', in that it returns null. This is expected because the DalvikVM does not keep the resources around after compiling. There are workarounds listed in the issue, but there may be another way to access the classes you desire.
Use the PackageManager to get a hold of an instance of ApplicationInfo. ApplicationInfo has a public field called sourceDir which is the full path (a String) to the location of the source directory for that application. Create a File from this String, and you should be able to navigate to your package within the source directory. Once there, you can use the method from my original answer to find the classes you are looking for.
String applicationSourceDir =
getPackageManager().getApplicationInfo(androidPackageName, 0).sourceDir;
/EDIT
You should be able to use the ClassLoader.getResource(String) to get a URL to your specific package (the passed in String being the package name you are interested in delimited by path separators rather than periods). With this URL you can then call getFile(), from which you can create a Java File to the package folder. Call packageFile.listFiles() from there, and you have your classes/subpackages.
Be recursive with the subpackages, and with the classes find the Class object using the static Class.forName(String) method.
In your java build process incorporate the class path scanning, generating injection data/code. This could then be ported too to Dalvik. It is even more efficient that dynamic scanning.