Calling an activity from an AndroidTestCase - android

I am writing an android test case which requires the execution of a seperate Activity to the Activity being tested (not for the sake of testing but just to gain access to the contentresolver so I can change some telephony settings).
Is it at all possible to start an activity from a test case or in another manner.
I am aware of the AndroidTestCase class used to test activities, an I am using it in my tests, however I need to use a ContentResolver to change telephony settings and then test the reaction of the activity under test so I need another application component to change these settings.
Note: I release the complexity behind multiple activity testing (requiring an ActivityManager) but I only want to use it's method to alter the settings so I could even have the logic in the onCreate method.

Android provides a special instrumentation framework for testing Activities. You must use this framework since Activities have a complex lifecycle that is un-invokable outside this provided framework. Look under the Testing link in the Developmentsection of the Android documentation for Activity Testing. If this doesn't answer your question, you might rephrase it a bit.
Edit
You should really be extending ActivityUnitTestCase to test an Activity, not AndroidTestCase. You get more functionality specific to what you need to test. If you extend ActivityUnitTestCase there is a function called launchActivity. It'll launch the activity you need and give you an instance of the activity so that you can call methods on it such as set, get, and finish. This should do anything you need for manipulating single and multiple activities at a time.
Example code:
#MediumTest
public class Test extends ActivityUniTestCase<HelloActivity> {
public Test(Class<HelloActivity> activityClass) {
super(activityClass);
}
#MediumTest
public void testLifeCycleCreate() {
HelloActivity hActivity = startActivity(new Intent(Intent.ACTION_MAIN), null, null);
getInstrumentation().callActivityOnStart(hActivity);
getInstrumentation().callActivityOnResume(hActivity);
GoodByeActivity gActivity = launchActivity("package.goodbye", GoodByeActivity.class, null);
gActivity.finish();
}
}

AndroidTestCase and ActivityInstrumentationTestCase2 both provide methods to get Context
AndroidTestCase:
getContext();
ActivityInstrumentationTestCase2
getInstrumentation().getContext();
You can use these contexts to launch another activity, however the permissions is adopted from the application under test, so in my case with the contentresolver I only have the same permission to alter settings I do in the application under test.
In my case this is no good so I had to create a seperate application with it's own permissions and a background service I was then able to control by launching intents using the context.

Related

What is the purpose of Application class in Android

What exactly is the purpose of Application class.
what are the benefits of extending it to a custom subclass
Why use it ?
Can global variables be stored in any other class achieve same goal as Application ?
Nice question !
Your application is a context that is always running while your activities and services are running.
It is also the first context to be created and the last to be destroyed.
Thus, it surrounds the life cycle of your app.
You can use the application class as a way to share data or components (for dependency injection for instance). For instance if you want to share a singleton between activities, you can create the instance in the application class and provide a getter, then all other contexts can get the singleton via
((cast to your class)getApplicationContext()).getFoo();
There may be some use cases where you need to do stuff before even your first activity is launched, then do it in the onCreate method of the application class.
On the other hand, you should never relie on the onDestroy method of the Application class, as it is not always called. There is no contract for that on Android.
But this is rare and, usually, you don't need to override the application class though. Dependency injection can be achieved in other ways by RoboGuice or Dagger for instance.
Two things makes this Class very useful:
Application class is instantiated before any other Activity.
It holds the Application Context
Context brings a host of resources for us: we can figure out some device properties, load some resources, initiate a SQLite database etc, etc.
All of this happens before any Activity loads, and all of this is globally available to the Activities.
Simple example of what I mean:
public class App extends Application{
private static Resources sResources;
//--I want to load strings resources from anywhere--
public static String loadStringResource(int resID) {
return sResources.getString(resID);
}
#Override
public void onCreate() {
super.onCreate();
sResources = getResources();
//---I want to load all preferences when my app starts---
PreferenceManager.setDefaultValues(this,R.xml.prefs,false);
}
}
Extending the Application class allows you to integrate into the application's lifecycle.
This is also useful to store global application-level information (though it's usually good to keep your activities 'independent')
The Application class is aware of the Application Context and is loaded when your app is loaded so it holds the proper callbacks for the application lifecycle before your activity starts. You most likely would not want to extend this class.
From the API docs:
There is normally no need to subclass Application. In most situation, static singletons can provide the same functionality in a more modular way. If your singleton needs a global context (for example to register broadcast receivers), the function to retrieve it can be given a Context which internally uses Context.getApplicationContext() when first constructing the singleton.
http://developer.android.com/reference/android/app/Application.html

I am trying to unit test a custom Dialog in Android and I can't seem to instantiate it

I am unit testing an application that includes a custom dialog. This dialog inherits from android.app.Dialog but requires a speciall subclass of Activity, let's call it CustomActivity, that provides some functions it needs.
I want to avoid instantiating one of the Activities from the tested application since I already have tests for them. I'm unit testing, not black-box-testing, so I want to run all the public functions in the dialog. This is not possible, however, without instantiating the dialog first and that requires a CustomActivity instance.
I've tried to create a mock subclass of CustomActivity and use that to launch the dialog, but I keep running into the same problem: The test application is not looking for activities in the test-application, only in the tested application. So I get "Unable to resolve activity".
I've also tried to create the activity myself, without using Instrumentation.launchActivity but that requires a context, which I don't have under InstrumentationTestCase. If I use AndroidTestCase instead, the provided context (via getContext) is just a ContextWrapper which doesn't seem to wrap any context, so I'm back to square one. I need to instantiate the activity first.
I've googled quite a bit and I can't believe I am the first person ever to need to unit test a Dialog. It seems to me that I would need something similar to the ActivitiTestCase2 but for dialogs that provide the necessary context.
What is the best way to create my dialog? Is there another way I haven't tried? Does anyone have an example of a custom dialog unit-test?
This sounds like an object-oriented problem rather than an Android problem. I think your core problem may be your tight coupling between the classes. Try introducing an interface in front of CustomActivity that exposes only the functions that your dialog needs, then mock the interface in your tests, instead of trying to create a mock subclass of the activity itself. Good luck!

Accessing Activity before it starts

I am using the InstrumentationTestCase class in order to unit test some things within an activity.
I need to be able to check the SharedPreferences's contents and edit them, before this activity is launched.
I cannot use the setUp method to create the Activity and access it's SharedPreferences object to edit it, and then close that activity before finishing the setUp method because it apparently is locking the tests processing.
I also cannot access the SharedPreferences after I have launched the activity inside the test because as soon as the Activity is launched, it will already change the SharedPreferences object and act according to it, before I had the chance to get it's reference.
I apparently cannot access the SharedPreferences before either, because I have no Activity object... and as soon as I do, it is already executing code and being launched...
So, my question is, is there any way to access the SharedPreferences (and any other Activity information) of this Activity before I have the Activity actually created through an Intent?
I cannot change it to an ActivityInstrumentationTestCase2 because my test uses a second activity in it's process, so I can't just change to this class and use it's setUp() method to access the SharedPreferences.
I found the best simpler way to do this through the instrumentation only, without having to edit the application's architecture or any of the access attributes.
I achieved it through this:
Instrumentation instrumentation = getInstrumentation();
instrumentation.getTargetContext().getSharedPreferences(..);
This way I can access the SharedPreferences before any Activity is launched by the instrumentation.
Thanks for all the help, hints and other alternatives anyway.
Well... To tell you frankly.. I am not able to visualize your scenario. But is checking for info in application is doable ?
Create a class which extends android.app.Application and specify class name in Manifests child application element.
Sample Code:
import android.app.Application;
public class MyApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
//try and access activity info here.
}
}
When your application is launched first class method to execture is onCreate of your application and has all the lifecyle events of that of any activity..
You must define extended application class in manifest by:
<application
android:name=".MyApplication"
android:label="#string/application_name">
I hope this ca give you some overview.
I haven't tried it, but if you set the mode to MODE_WORLD_READABLE and possibly MODE_WORLD_WRITEABLE instead of MODE_PRIVATE, I would think you could access the shared preferences from another application before the activity under test starts.
You could probably also use a different activity or service within the apk, or another apk that establishes a shared user ID and has the same certificate, to do the access without changing the access mode.

Different Instance of Applicationcontext in Broadcastreceiver

I want to access a "global" variable in my MyApp(extends Application) from a broadcastreceiver (registered in the manifest) and e.g. multiple activities. Now I seem to have different instances of my MyApp: one for the BCR and one for the activities. Could sb help me with my problem?
thanks alot
Joerg
What I get from this is that you are trying to create a method to having a single Context object. First off, to do this you would need a Singleton Pattern of MyApp to create your "global" variable. However I would advice against this for these reasons:
Different application components by default have different contexts (base, application).
A BroadcastReceiver defined in the manifest is invoked by the OS, not by your application.
Using a Singleton Pattern for a context object will lead to some very nasty dependencies.
You are going against the design and beauty of the Android Framework.
I would suspect the reason you are doing this is so your MyApp class can start different activities. This makes sense, but... you can get a Context Object from almost anywhere. Many things in Android extend the ContextWrapper class (think Java Objects with the Object class). So there is really no reason to ever have a "global" instance of this. In fact your BroadcastReceiver's onReceive() method accepts a context parameter. You can use this to start activities and what not.
If this is not why you are wanting the MyApp singleton class - and there are justifiable reasons for needing it, I would look at the implementation designed by Bill Pugh as it is the safest in Java taking into account thread synchronization and locking.
Hope this helps. Remember, don't fight the SDK, let it work for you!
I had a similar problem, I was able to access an object in the activity using this pattern:
public class MyReceiver extends android.content.BroadcastReceiver {
private Object _object;
public MyReceiver(Someobject) {
_object = the object;
}
#Override
public void onReceive(Context context, Intent intent) {
Do something to the object.
}
}
Then call MyReceiver(theobject) instead of new BroadcastReceiver().

How to declare global variables in Android?

I am creating an application which requires login. I created the main and the login activity.
In the main activity onCreate method I added the following condition:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
...
loadSettings();
if(strSessionString == null)
{
login();
}
...
}
The onActivityResult method which is executed when the login form terminates looks like this:
#Override
public void onActivityResult(int requestCode,
int resultCode,
Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode)
{
case(SHOW_SUBACTICITY_LOGIN):
{
if(resultCode == Activity.RESULT_OK)
{
strSessionString = data.getStringExtra(Login.SESSIONSTRING);
connectionAvailable = true;
strUsername = data.getStringExtra(Login.USERNAME);
}
}
}
The problem is the login form sometimes appears twice (the login() method is called twice) and also when the phone keyboard slides the login form appears again and I guess the problem is the variable strSessionString.
Does anyone know how to set the variable global in order to avoid login form appearing after the user already successfully authenticates?
I wrote this answer back in '09 when Android was relatively new, and there were many not well established areas in Android development. I have added a long addendum at the bottom of this post, addressing some criticism, and detailing a philosophical disagreement I have with the use of Singletons rather than subclassing Application. Read it at your own risk.
ORIGINAL ANSWER:
The more general problem you are encountering is how to save state across several Activities and all parts of your application. A static variable (for instance, a singleton) is a common Java way of achieving this. I have found however, that a more elegant way in Android is to associate your state with the Application context.
As you know, each Activity is also a Context, which is information about its execution environment in the broadest sense. Your application also has a context, and Android guarantees that it will exist as a single instance across your application.
The way to do this is to create your own subclass of android.app.Application, and then specify that class in the application tag in your manifest. Now Android will automatically create an instance of that class and make it available for your entire application. You can access it from any context using the Context.getApplicationContext() method (Activity also provides a method getApplication() which has the exact same effect). Following is an extremely simplified example, with caveats to follow:
class MyApp extends Application {
private String myState;
public String getState(){
return myState;
}
public void setState(String s){
myState = s;
}
}
class Blah extends Activity {
#Override
public void onCreate(Bundle b){
...
MyApp appState = ((MyApp)getApplicationContext());
String state = appState.getState();
...
}
}
This has essentially the same effect as using a static variable or singleton, but integrates quite well into the existing Android framework. Note that this will not work across processes (should your app be one of the rare ones that has multiple processes).
Something to note from the example above; suppose we had instead done something like:
class MyApp extends Application {
private String myState = /* complicated and slow initialization */;
public String getState(){
return myState;
}
}
Now this slow initialization (such as hitting disk, hitting network, anything blocking, etc) will be performed every time Application is instantiated! You may think, well, this is only once for the process and I'll have to pay the cost anyways, right? For instance, as Dianne Hackborn mentions below, it is entirely possible for your process to be instantiated -just- to handle a background broadcast event. If your broadcast processing has no need for this state you have potentially just done a whole series of complicated and slow operations for nothing. Lazy instantiation is the name of the game here. The following is a slightly more complicated way of using Application which makes more sense for anything but the simplest of uses:
class MyApp extends Application {
private MyStateManager myStateManager = new MyStateManager();
public MyStateManager getStateManager(){
return myStateManager ;
}
}
class MyStateManager {
MyStateManager() {
/* this should be fast */
}
String getState() {
/* if necessary, perform blocking calls here */
/* make sure to deal with any multithreading/synchronicity issues */
...
return state;
}
}
class Blah extends Activity {
#Override
public void onCreate(Bundle b){
...
MyStateManager stateManager = ((MyApp)getApplicationContext()).getStateManager();
String state = stateManager.getState();
...
}
}
While I prefer Application subclassing to using singletons here as the more elegant solution, I would rather developers use singletons if really necessary over not thinking at all through the performance and multithreading implications of associating state with the Application subclass.
NOTE 1: Also as anticafe commented, in order to correctly tie your Application override to your application a tag is necessary in the manifest file. Again, see the Android docs for more info. An example:
<application
android:name="my.application.MyApp"
android:icon="..."
android:label="...">
</application>
NOTE 2: user608578 asks below how this works with managing native object lifecycles. I am not up to speed on using native code with Android in the slightest, and I am not qualified to answer how that would interact with my solution. If someone does have an answer to this, I am willing to credit them and put the information in this post for maximum visibility.
ADDENDUM:
As some people have noted, this is not a solution for persistent state, something I perhaps should have emphasized more in the original answer. I.e. this is not meant to be a solution for saving user or other information that is meant to be persisted across application lifetimes. Thus, I consider most criticism below related to Applications being killed at any time, etc..., moot, as anything that ever needed to be persisted to disk should not be stored through an Application subclass. It is meant to be a solution for storing temporary, easily re-creatable application state (whether a user is logged in for example) and components which are single instance (application network manager for example) (NOT singleton!) in nature.
Dayerman has been kind enough to point out an interesting conversation with Reto Meier and Dianne Hackborn in which use of Application subclasses is discouraged in favor of Singleton patterns. Somatik also pointed out something of this nature earlier, although I didn't see it at the time. Because of Reto and Dianne's roles in maintaining the Android platform, I cannot in good faith recommend ignoring their advice. What they say, goes. I do wish to disagree with the opinions, expressed with regards to preferring Singleton over Application subclasses. In my disagreement I will be making use of concepts best explained in this StackExchange explanation of the Singleton design pattern, so that I do not have to define terms in this answer. I highly encourage skimming the link before continuing. Point by point:
Dianne states, "There is no reason to subclass from Application. It is no different than making a singleton..." This first claim is incorrect. There are two main reasons for this. 1) The Application class provides a better lifetime guarantee for an application developer; it is guaranteed to have the lifetime of the application. A singleton is not EXPLICITLY tied to the lifetime of the application (although it is effectively). This may be a non-issue for your average application developer, but I would argue this is exactly the type of contract the Android API should be offering, and it provides much more flexibility to the Android system as well, by minimizing the lifetime of associated data. 2) The Application class provides the application developer with a single instance holder for state, which is very different from a Singleton holder of state. For a list of the differences, see the Singleton explanation link above.
Dianne continues, "...just likely to be something you regret in the future as you find your Application object becoming this big tangled mess of what should be independent application logic." This is certainly not incorrect, but this is not a reason for choosing Singleton over Application subclass. None of Diane's arguments provide a reason that using a Singleton is better than an Application subclass, all she attempts to establish is that using a Singleton is no worse than an Application subclass, which I believe is false.
She continues, "And this leads more naturally to how you should be managing these things -- initializing them on demand." This ignores the fact that there is no reason you cannot initialize on demand using an Application subclass as well. Again there is no difference.
Dianne ends with "The framework itself has tons and tons of singletons for all the little shared data it maintains for the app, such as caches of loaded resources, pools of objects, etc. It works great." I am not arguing that using Singletons cannot work fine or are not a legitimate alternative. I am arguing that Singletons do not provide as strong a contract with the Android system as using an Application subclass, and further that using Singletons generally points to inflexible design, which is not easily modified, and leads to many problems down the road. IMHO, the strong contract the Android API offers to developer applications is one of the most appealing and pleasing aspects of programming with Android, and helped lead to early developer adoption which drove the Android platform to the success it has today. Suggesting using Singletons is implicitly moving away from a strong API contract, and in my opinion, weakens the Android framework.
Dianne has commented below as well, mentioning an additional downside to using Application subclasses, they may encourage or make it easier to write less performance code. This is very true, and I have edited this answer to emphasize the importance of considering perf here, and taking the correct approach if you're using Application subclassing. As Dianne states, it is important to remember that your Application class will be instantiated every time your process is loaded (could be multiple times at once if your application runs in multiple processes!) even if the process is only being loaded for a background broadcast event. It is therefore important to use the Application class more as a repository for pointers to shared components of your application rather than as a place to do any processing!
I leave you with the following list of downsides to Singletons, as stolen from the earlier StackExchange link:
Inability to use abstract or interface classes;
Inability to subclass;
High coupling across the application (difficult to modify);
Difficult to test (can't fake/mock in unit tests);
Difficult to parallelize in the case of mutable state (requires extensive locking);
and add my own:
Unclear and unmanageable lifetime contract unsuited for Android (or most other) development;
Create this subclass
public class MyApp extends Application {
String foo;
}
In the AndroidManifest.xml add android:name
Example
<application android:name=".MyApp"
android:icon="#drawable/icon"
android:label="#string/app_name">
The suggested by Soonil way of keeping a state for the application is good, however it has one weak point - there are cases when OS kills the entire application process. Here is the documentation on this - Processes and lifecycles.
Consider a case - your app goes into the background because somebody is calling you (Phone app is in the foreground now). In this case && under some other conditions (check the above link for what they could be) the OS may kill your application process, including the Application subclass instance. As a result the state is lost. When you later return to the application, then the OS will restore its activity stack and Application subclass instance, however the myState field will be null.
AFAIK, the only way to guarantee state safety is to use any sort of persisting the state, e.g. using a private for the application file or SharedPrefernces (it eventually uses a private for the application file in the internal filesystem).
Just a note ..
add:
android:name=".Globals"
or whatever you named your subclass to the existing <application> tag. I kept trying to add another <application> tag to the manifest and would get an exception.
What about ensuring the collection of native memory with such global structures?
Activities have an onPause/onDestroy() method that's called upon destruction, but the Application class has no equivalents. What mechanism are recommended to ensure that global structures (especially those containing references to native memory) are garbage collected appropriately when the application is either killed or the task stack is put in the background?
I couldn't find how to specify the application tag either, but after a lot of Googling, it became obvious from the manifest file docs: use android:name, in addition to the default icon and label in the application stanza.
android:name
The fully qualified name of an Application subclass implemented for the application. When the application process is started, this class is instantiated before any of the application's components.
The subclass is optional; most applications won't need one. In the absence of a subclass, Android uses an instance of the base Application class.
Just you need to define an application name like below which will work:
<application
android:name="ApplicationName" android:icon="#drawable/icon">
</application>
Like there was discussed above OS could kill the APPLICATION without any notification (there is no onDestroy event) so there is no way to save these global variables.
SharedPreferences could be a solution EXCEPT you have COMPLEX STRUCTURED variables (in my case I had integer array to store the IDs that the user has already handled). The problem with the SharedPreferences is that it is hard to store and retrieve these structures each time the values needed.
In my case I had a background SERVICE so I could move this variables to there and because the service has onDestroy event, I could save those values easily.
If some variables are stored in sqlite and you must use them in most activities in your app.
then Application maybe the best way to achieve it.
Query the variables from database when application started and store them in a field.
Then you can use these variables in your activities.
So find the right way, and there is no best way.
You can have a static field to store this kind of state. Or put it to the resource Bundle and restore from there on onCreate(Bundle savedInstanceState). Just make sure you entirely understand Android app managed lifecycle (e.g. why login() gets called on keyboard orientation change).
DO N'T Use another <application> tag in manifest file.Just do one change in existing <application> tag , add this line android:name=".ApplicationName" where, ApplicationName will be name of your subclass(use to store global) that, you is about to create.
so, finally your ONE AND ONLY <application> tag in manifest file should look like this :-
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/Theme.AppCompat.NoActionBar"
android:name=".ApplicationName"
>
you can use Intents , Sqlite , or Shared Preferences . When it comes to the media storage, like documents , photos , and videos, you may create the new files instead.
You can do this using two approaches:
Using Application class
Using Shared Preferences
Using Application class
Example:
class SessionManager extends Application{
String sessionKey;
setSessionKey(String key){
this.sessionKey=key;
}
String getSessisonKey(){
return this.sessionKey;
}
}
You can use above class to implement login in your MainActivity as below. Code will look something like this:
#override
public void onCreate (Bundle savedInstanceState){
// you will this key when first time login is successful.
SessionManager session= (SessionManager)getApplicationContext();
String key=getSessisonKey.getKey();
//Use this key to identify whether session is alive or not.
}
This method will work for temporary storage. You really do not any idea when operating system is gonna kill the application, because of low memory.
When your application is in background and user is navigating through other application which demands more memory to run, then your application will be killed since operating system given more priority to foreground processes than background.
Hence your application object will be null before user logs out. Hence for this I recommend to use second method Specified above.
Using shared preferences.
String MYPREF="com.your.application.session"
SharedPreferences pref= context.getSharedPreferences(MyPREF,MODE_PRIVATE);
//Insert key as below:
Editot editor= pref.edit();
editor.putString("key","value");
editor.commit();
//Get key as below.
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
String key= getResources().getString("key");
On activity result is called before on resume. So move you login check to on resume and your second login can be blocked once the secomd activity has returned a positive result. On resume is called every time so there is not worries of it not being called the first time.
The approach of subclassing has also been used by the BARACUS framework. From my point of view subclassing Application was intended to work with the lifecycles of Android; this is what any Application Container does. Instead of having globals then, I register beans to this context an let them beeing injected into any class manageable by the context. Every injected bean instance actually is a singleton.
See this example for details
Why do manual work if you can have so much more?
class GlobaleVariableDemo extends Application {
private String myGlobalState;
public String getGlobalState(){
return myGlobalState;
}
public void setGlobalState(String s){
myGlobalState = s;
}
}
class Demo extends Activity {
#Override
public void onCreate(Bundle b){
...
GlobaleVariableDemo appState = ((GlobaleVariableDemo)getApplicationContext());
String state = appState.getGlobalState();
...
}
}
You could create a class that extends Application class and then declare your variable as a field of that class and providing getter method for it.
public class MyApplication extends Application {
private String str = "My String";
synchronized public String getMyString {
return str;
}
}
And then to access that variable in your Activity, use this:
MyApplication application = (MyApplication) getApplication();
String myVar = application.getMyString();

Categories

Resources