[8] Android Context - mariamaged/Java-Android-Kotlin GitHub Wiki
Android - Context
MainActivity
extends
AppCompatActivity, whichextends
Activity, whichimplements
the Context interface.
1. Where Did It Come From?
- In mid-2000, the dominant form of Java programming was for
server-side Web development
, using:- Servlets.
- WARs.
- And so on.
- In Web development, there is often some form of a "session" object.
- At minimum, this object represents the
user's session with the server
and represents a a place where the servlet can stash values from one request that might be used in a subsequent request from the same user.
- At minimum, this object represents the
- In Android, a lot of functionality routes through a Context, either because:
- Our only ways of accomplishing a particular thing involve functions on a Context.
- Our only way to get at some other object that accomplishes that thing is by calling a function on the Context.
2. The Major Types of Context
- Context is an interface, so in theory anything could be a Context.
2.1 Context from Components
- Activity.
- Implements Context.
- We can call getString() on.
- Service.
- Implements Context.
- BroadcastReceiver.
- Where you get a Context via its
onReceive()
function that you implement or inherit.
- Where you get a Context via its
- ContentProvider.
- Where you get a Context by calling
getContext()
when you need one.
- Where you get a Context by calling
2.2 Application
- There is one other "root" Context besides your components: Application.
- Each Android app has an Application singleton.
- This object is created when the process is created, and it
lives through the life of that process
.
- This object is created when the process is created, and it
- In your regular application code, you get access to this singleton: by calling
getApplicationContext()
onsome other Context
.
3. Instrumented Tests
Note that in testing we get a Context in other ways.
Kotlin
package com.mariamaged.helloworld
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.mariamaged.helloworld", appContext.packageName)
}
}
Java
package com.mariamaged.helloworld;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
@RunWith(AndroidJUnit.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.mariamaged.helloworld", appContext.getPackageName());
}
}
3. Key Context Features
- Many things take a Context.
- Constructors for all of our widgets and containers, for example, take a Context as a parameter.
3.1 Access to Resources and Assets
Resources
- If you want to (1)
get the value
or (2)otherwise use a resource
, you will wind up using a Context. - Sometimes, that comes from calling
convenience functions
on Context functions, such asgetString()
.
In general, though, access to resources comes from a Resources object, and you get one of those by calling
getResources()
on a Context.Resources has functions to retrieve most types of resources:
- Strings.
- Dimensions.
- Colors, and so on.
- The convenience functions on Context simply delegate to the Resource object- for example, getString() on Context just forwards your request to
getString()
on Resources.
Assets
- In addition to resources, an Android app can also have assets, found in
assets/ directory
that sits alongside directories likesrc/
andres/
. - If you package assets this way with your app, calling
getAssets()
on a Context gives you an AssetManager. - From there, you can work with the assets, such as by calling
open()
to get an InputStream from which you can read an asset's content.
3.2 Access to Root Directories
- Resources and assets are packaged with the app.
- Beyond those, we have the ability to write to files on the local filesystem and read them back later.
- On the whole, this is standard I/O using Java classes like:
- File.
- InputStream.
- OutputWriter.
The big limitation is where we can read and write.
3.3 Access to System Services
- Lots of stuff used by your app is actually managed outside of your app.
- For example, suppose that you want to find out the device's location.
- Your app code does not work with
GPS hardware directly
. - Instead, it will work with a
LocationManager
, or something that wraps around aLocationManager
. LocationManager
: is a "System Service", and in turn will talk to other parts of the OS that, eventually, work with the GPS hardware.
- Your app code does not work with
Whenever you need access to a "system service", the typical approach to get one is to call
getSystemService()
on a Context.
- Occasionally, there will be other approaches:
- Some system services have a function that you can use to get an instance by way of a Context, such as
LayoutInflator.from()
. - Some system services have convenience functions on Context, such as
getPackageManager()
to get aPackageManager
instance.
- Some system services have a function that you can use to get an instance by way of a Context, such as
4. Know Your Context
As your app grows, you will start to having classes that are not Android components and do not have direct access to some Context.
- Instead, they will be talking with your Web Services.
- Or storing things in a local database.
- Or performing any number of other tasks that are important for your app.
- In an ideal world, few of these classes will need a Context.
- For those that do, you will need to decide what Context they will use:
Use | Choice |
---|---|
Do they take a Context as a function parameter for a particular operation. | So the caller chooses the Context. |
Do they take a Context as a constructor parameter. | So the choice of Context has to take into account how long this object is needed. |
Do they do something more elaborate. | Such as dependency injection. |