Can't use a public static method? - java

This is confusing. I'm look at the Android 2.2.2_r1 source code for the NotificationManager class, and I see the method getService() which is defined as public and static. However, eclipse is telling me:
The method getService() is undefined for the type NotificationManager
on the line
Object o = NotificationManager.getService();
My project is building against Android 2.2/ API Level 8. I tried to use reflection to see the method names and modifiers, and sure enough, I got back
public static getService
Am I missing something here? Why would eclipse tell me this method doesn't exist?

You will find a very detailed answer in this post.
In short: Because you compile against the android.jar, which has all hidden methods (like the one you are trying to access) removed. They will only be there on runtime, for internal android usage.
But since you perhaps also need it. The right way to access the NotificationManager is via the getSystemService method of a context:
NotificationManager nm = (NotificationManager)ctx.getSystemService(Context.NOTIFICATION_SERVICE);
With context being a valid context (like your current activity).

Related

Getting int value of Resource from Application Class

I'm setting up a notification class that needs to be independent of any Activity, but called through my main Application class. I'm having trouble accessing resources.
The Application class gets its context via context.getApplicationContext(), and this is passed to the constructor of my notification class:
NotificationService notificationService = new NotificationService(context, notifications);
I need to set the small icon from my Drawables, and when I add the R.drawable.tv_logo_notext_bw resource, the compiler cannot locate it:
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setSmallIcon(R.drawable.tv_logo_notext_bw);
Obviously, it needs a context, but the context was passed to the constructor of both my notification class and the NotificationCompatBuilder class, so I don't understand why the compiler cannot see the drawable.
Am I missing some crucial step?
Resource Id's are public static filed and being auto-generated by your Gradle & IDE, this means you should be able to call the from any part of you project,
your code looks fine.
Try the next step to "Refresh" your IDE (Android Studio)
1. Try to rebuild your project Build | Rebuild
2. Also try Choose File | Invalidate Caches/Restart.

Inject Context to activity

I am combining a static code analysis with a dynamic one. I basically create a new activity and set it up as the starting activity. During the run various methods in existing activities should be called.
I can call e.g. onCreate from outside, however, the super call to Activity will fail (or calls to SharedPreferences or other interesting classes) since Android does some initialization stuff when using the intents in order to call an activity (e.g. setting the context). But I need to somehow call methods like onCreate or onPause from outside while giving the target activity a valid context.
In my newly created activity I have got a valid context. I tried to pass it via calling ContextWrapper.attachBaseContext, but there is still a NullPointerException somewhere in Android due a the missing context. Is there some way to hack this somehow into a working state? Using reflection or other hacks would be no problem, since it is for analysis purposes only.
Thank you very much for any tips. I'd be able to modify the analyzed apps in any way to get this working.
However: Using an Intent is no option, since I cannot control which Activity-methods are being called, when and how often. I know that android has not been made for calling these methods directly, but it is not a common use case either :);
I have created a hack, which seems to help (I can get a valid context in the hacked activity). Let's see how far I get using this.
public static void hack(Activity hack, Activity main) {
try {
Field mActivityInfo = getField(Activity.class, "mActivityInfo");
mActivityInfo.set(hack, getClass("android.content.pm.ActivityInfo").newInstance());
Field mFragments = getField(Activity.class, "mFragments");
Field mContainer = getField(Activity.class, "mContainer");
Field mApplication = getField(Activity.class, "mApplication");
Field mWindow = getField(Activity.class, "mWindow");
Class FragmentManagerImpl = getClass("android.app.FragmentManagerImpl");
FragmentManager manager = (FragmentManager) mFragments.get(hack);
mApplication.set(hack, main.getApplication());
mWindow.set(hack, main.getWindow());
Class<?> FragmentContainer = getClass("android.app.FragmentContainer");
Method attachActivity = getMethod(FragmentManagerImpl, "attachActivity", Activity.class, FragmentContainer, Fragment.class);
attachActivity.invoke(manager, hack, mContainer.get(hack), null);
Method attachBaseContext = getMethod(ContextWrapper.class, "attachBaseContext", Context.class);
attachBaseContext.invoke(hack, new HackContext(main));
System.out.println("Hack performed");
} catch (Exception e) {
e.printStackTrace();
System.err.println("Hack failed :(");
}
}

Testing SQLiteOpenHelper subclass with JUnit

I am writing JUnit tests for my Android app. I have read through the Android developer resources (testing fundamentals, Spinner example test, etc.). Now I want to test my SQLiteOpenHelper subclass independently of the Activities which use it. My idea is to extend ActivityInstrumentationTestCase2<Activity>. Is it okay to simply use Activity as the generic parameter or do I need a subclass? Also, am I headed in the right direction here, or is there a better way to test my SQLiteOpenHelper subclass?
I was looking for an answer to exactly this problem, and found this link as well as another interesting related question here:
Android JUnit test for SQLiteOpenHelper
The accepted answer by #Pietro shows some simple code, using a basic AndroidTestCase, which will help directly to answer the question.
public class DatabaseTest extends AndroidTestCase {
private MyDatabase db;
public void setUp(){
RenamingDelegatingContext context
= new RenamingDelegatingContext(getContext(), "test_");
db = new MyDatabase(context);
}
public void testAddEntry(){
// Here I have my new database which is not connected to the standard database of the App
}
public void tearDown() throws Exception{
db.close();
super.tearDown();
}
}
I was happy at how simple it looks. In my case I'm new to Android testing, so even the simple stuff seems difficult at the moment.
But the interesting part which is key, is using the RenamingDelegatingContext class as your "context" instead of just using a normal context. This seems to build on the comments made by #Jens.
This class wraps a given context and delegates most operations to that context. The useful part is that it performs database and file operations with a renamed database/file name (see documentation online).
This allows your TEST code to use an actual different instance of the database to your PRODUCTION code - at least in my case this is going to be useful.
Here is another related post where the accepted answer says pretty much the same thing:
Testing database on Android: ProviderTestCase2 or RenamingDelegatingContext?
Some useful tips in there about using ContentProvider instead (but that's a different issue for another day).
following link talk about testing in android:
http://developer.android.com/tools/testing/testing_android.html
may be you have already seen it just posting it in case you have missed going through it.. it is a very good resource to learn about junit in android...
For testing with Android Studio,
You should use MockContext instead of RenamingDelegatingContext.
If you use RenamingDelegatingContext, You would get context as null.
For AndroidTestCase, getContext() would return null. And for InstrumentationTestCase, getInstrumentation().getContext() would return null.
For further information, see this answer. https://stackoverflow.com/a/29063736/1020456

Protected fields not visible to subclasses

I'm writing a custom view that directly extends android.view.View. If I try to access fields mScrollX or mScrollY, I see an error that the field "cannot be resolved or is not a field." The source code for android.view.View has mScrollX, mScrollY, and similar variables declared protected. How is it that my direct subclass cannot access protected fields of its parent class? (Classes like ScrollView apparently can.)
P.S. I realize that I can call getScrollX(), but I want to update these fields; calling setScroll() has side effects that I don't want.
It's because they are not part of the Android SDK.
Here is the source code for mScrollX:
/**
* The offset, in pixels, by which the content of this view is scrolled
* horizontally.
* {#hide}
*/
#ViewDebug.ExportedProperty(category = "scrolling")
protected int mScrollX;
You will notice the #hide annotation. That means this is not part of the Android SDK. The part of the build process that creates the Android SDK will not include this data member in the stub edition of android.view.View that is in the android.jar file that you are compiling against.
The #hide annotation is used for things that for internal purposes needed to be public or protected but are not considered something SDK developers should be using.
Please find other solutions for whatever problem you are experiencing.
It's very straight forward: notice the #hide annotation above these variables.
It's an Android-specific annotation that hides the fields/methods from the public SDK. That's why you can't access them directly.
Romain Guy mentioned it in this post.
You could try setting the fields with reflection:
import java.lang.reflect.Field;
// ...
try {
Field scrollXField = View.class.getDeclaredField("mScrollX");
scrollXField.setAccessible(true);
scrollXField.set(this, myNewValue);
} catch (Exception ex) {
// oops, android changed the implementation. sucks to be you.
}
Note, however, that you're relying on undocumented and unsupported behavior when you do this, and so you should be prepared for things to break on some devices or in future versions.

Context in android

i am a newbie.Please explain what all things are passed through a context.Like when constructing an object for the following class..
public class myclass{
public myclass (Context context){....}
}
You get a lot of possibilities to check for or change System or application properties.
You will find a detailed version of all the functions that are available with the context in the api documentation of android:
http://developer.android.com/reference/android/content/Context.html
So you will be able for example to start a service (to run part of the application in the background) through context.startService(Intent service). You'll need to pass an Intent (if you don't know what an intent is I would read the Dev Guide: http:**developer.android.com/guide/topics/fundamentals.html first. You could do that anyway, there are plenty of good descriptions and examples.).
Sorry for the crippled link, I'm not allowed to post more than one link per post...

Categories

Resources