Layered Architecture
From top down:
- Android applications: 应用层 games, browsers, etc.
- Android Framwork: Interfaces and classes for the development of Android applications. Android APIs -- UI, resources, content provides, etc.
- Runtime: DVM (Dalvik Virtual Machine) or ART(Android RunTime)
- Libraries: Web browser engine, libc, SQLite database, SSL, etc.
- Linux Kernel: It is responsible for device drivers, device management, memory management, power management, and resource access.
Compiling
From Android 5.0 and on: Done by Gradle
- Generate Java source files (e.g., from resource files, which are written XML used to generate Java code)
- Compile Java code into JVM bytecode
- “dex” the JVM bytecode into Dalvik bytecode
- Pack in assets and graphics into an APK (like a ZIP)
- Cryptographically sign the APK file to verify it
- Load it onto the device
Project Content
app/ folder
- Android Manifest: "config" file for the project
- "java" folder: contains the Java source code for your project
- "res" folder: contains resources like "layout" (UI), "
drawable"
(graphics), "mipmap" (launcher icons), "values" (constants)
Gradle scripts
build.gradle
: Top-level Gradle build; project-level (for building!)app/build.gradle
: Gradle build specific to the app use this one to customize project!. We can change the Target SDK in here!
Activities
An Activity is an application component that provides a screen with which users can interact in order to do something
A place to hold state and data, and tell to Android what to show on the display. It functions much like a Controller (in Model-View-Controller sense)
A Java class that inherits "Activity" class in the framework, we extend all original methods in the framework.
LifeCycle
Each lifecycle event is a callback method:
Method | When is it Called | Typical Action |
onCreate() | When the Activity is first created/instantiated |
搭起activity的整体框架 Can be called only once |
onStart() | Just before the Activity UI become visible | Can be called more than once: Every time user navigates back |
onResume() | Just before user starts interacting, after which the activity begins running | Sometimes there is another activity in front, the activity below is visible, but is not interactable, i.e. onResume() |
onPause() | When the user is about to start another Activity, or the activity is temporarily covered by another one. -- Mirror to | Quickly and temporarily store unsaved changes, or stop animations or video playback |
onStop() | When UI are no longer visible -- Mirror to onStart() | Persist any state information (e.g., saving the user’s document or game state) |
onRestart() | When Activity is returned from a Stopped state | Allows to run a different code up return |
onDestroy() | Called when the Activity is about to be closed | the user ended the application, or the OS is trying to save memory and kills the App. |
Launch Mode
Activity的四种启动模式对比 - 简书https://www.jianshu.com/p/a5e19b3d1398
1.Standard(标准模式-默认)
2.SingleTop(栈顶复用模式)
3.SingleTask(栈内复用模式)
4.SingleInstance(全局唯一模式)
Bundling
A Bundle is an object that stores key-value pairs and are used for temporarily “bunding” small amounts of information -- only for basic types (numbers, Strings).
Example usage:
In the onCreate()
callback method, Bundle is used as a param to store current Activity states. Sometimes it can store a UI layout element so that all info user left on that UI is preserved.
Logging
We use android.util.Log class for logging, and all messages can be filtered, categorized, sorted, etc.
Method | Usage |
Log.v() | Verbose, development messages |
Log.d() | Debug, lower-level messages |
Log.i() | Info, user-level messages |
Log.w() | Warning |
Log.e() | Errors |
Finding view elements by id
findViewById():
“finds” the appropriate XML element with the given id, returns a View object, casting needed (like Button).
Set action to a view gadget
.setOnClickListener(): Pass an anonymous class as an argument to set it as the listener.
Intent
An intent is a message that allows Activities to communicate, even though they don’t have references to each other (and thus we can’t just call a method on them).
Intent creates objects that can be “given” to another component (referred to as a target), which can then react on that.
Explicit Intent
To start another activity.
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
- Arguments: Context (current activity class), and Target (destination activity)
startActivity(intent);
This method “send” the message to the operating system, which will deliver the Intent to the appropriate Activity, telling that Activity to start as soon as it receives the message.
Use the "back" button to return
Extras
// Including Extra
intent.putExtra("package.name.key","value");
// Receiving Extra
//in onCreate();
Bundle extras = getIntent().getExtras(); //All activities are started with an Intent!
String value = extras.getString("key");
- Every extra name should be in the form -- "PACKAGE.NAME.KEY"
- Each extra entry called a Bundle -- a set of primitive key-value pairs
Context
An abstract class (and a superclass of
Activity
) that acts as a reference for information about the current running environment
- Represents environmental info: Where is this running? Is there a keyboard plugged-in?
- Two types of Context
- Application Context: The environmental info of the whole application
- Activity Context: The environmental info of a specific activity (preferred type of context because it won't cause mem-leak) -- Use "this" to refer to the current activity
Implicit Intent
To start another Application
We need to specify
- Action: what the application will do
- Data: some data that applicatino will need
// Create an intent to dial a number
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:206-685-1622"));
// If the returned application is not null, launch the Application
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
Note: if there is more than one application to use, user will pick one of them.
Intents for a Response
startActivityForResult()
- Launch the resolved Activity.
- Once that Action is finished, the launched Activity will send another Intent back to us
- We can then react to in order to handle the result.
Take a picture and return it
- Implicit intent to take a picture
static final int REQUEST_IMAGE_CAPTURE = 1;
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
- MainActivity get the image in intent extra
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundle extras = data.getExtras(); // Extract extra
Bitmap imageBitmap = (Bitmap) extras.get("data"); // Extract Image
mImageView.setImageBitmap(imageBitmap); // Display Image
}
}
Using Intent Filters
The idea is that we’re “hearing” all the intents, BUT we’re “filtering” for the ones that are relevant to us. Like sorting out the junk mail.
- We specify <intent-filter> inside the manifest
- The tag is nested inside the element that it applies to (e.g., the
<activity>
) - The tag contains a
<action android:name="action">
filter, which describes the Action we can respond to. - The tag contains a
<data ...>
filter, which describes the type of data we can respond to. - The tag contains a
<category android:name="category">
filter, which is a “more information” piece. - <category> filter must include the
DEFAULT
category to receive implicit intents (i.e. to usestartActivity()
andstartActivityForResult
).
<activity android:name="SecondActivity">
<intent-filter>
<action android:name="android.intent.action.DIAL"/>
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="tel" />
</intent-filter>
</activity>
- Note: the data filter selects the Uri that looks like a phone number, the action filter selects the action DIAL.
Pending Intent
A
PendingIntent
is a token that you give to a foreign application (e.g.NotificationManager
,AlarmManager
, Home ScreenAppWidgetManager
, or other 3rd party applications), which allows the foreign application to use your application's permissions to execute a predefined piece of code.If you give the foreign application an Intent, it will execute your
Intent
with its own permissions. But if you give the foreign application aPendingIntent
, that application will execute yourIntent
using your application's permission.
Broadcast
A message that can be heard by any application on device. (security alert)
Receive Broadcast
- Subclass a BroadcastReceiver (A base class that is used by an class that can receive broadcast Intents)
- Implement the
onReceive(Context, Intent)
callback in order to handle when broadcasts are received. - Register our receiver
- Option 1: in Manifest, put an
<intent-filter>
inside of this to filter for broadcasts we care about - Option 2: in Code, good for temporarily listen for some kind of events, or for dynamically listener.
- Option 1: in Manifest, put an
Send an SMS message
Get defualt SMS manager
SmsManager smsManager = SmsManager.getDefault();
Set up intent & pending intent
public static final String ACTION_SMS_STATUS = "edu.uw.intentdemo.ACTION_SMS_STATUS";
...
Intent intent = new Intent(ACTION_SMS_STATUS);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, intent, 0);
- Define custom intent: ACTION_SMS_STATUS
- Create an implicit intent
- Create a pending intent: specify
content
that should send the intent, then a request code (e.g., for result callbacks if we wanted), then theIntent
, and finally any extra flags (none for now
Set message to send
smsManager.sendTextMessage("5554", null, "This is a test message!", pendingIntent, null);
// target, message
- Second null: Pending Intent for when messages are sent
- Last null: Pending Intent for when messages are delivered
Set Broadcast Receiver
if(intent.getAction() == MainActivity.ACTION_SMS_STATUS) {
if (getResultCode() == Activity.RESULT_OK) {
Toast.makeText(context, "Message sent!", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(context, "Error sending message", Toast.LENGTH_SHORT).show();
}
}
Note: BroadcastReceiver reacts to the intent it receives
Get Permission
<uses-permission android:name="android.permission.SEND_SMS" />
Using ActionViews & ActionProvider
- ActionViews: an action that provides rich functionality within the app bar
- ActionProvider: an action with its own customized layout. It may show the layout upon a click.
How Android Manages tasks (activities)
Android uses a stack to keep track of activities:
- Start a new Activity: Android instantiates that object and puts it on the top of a stack
- User click back button: Current activity is poped off of a stack, start the activity on top of the stack
Tasks
A Task is a collection of Activities arranged in a Stack, and there can be multiple Tasks in the background of your device.
- Each task is a stack of activities (e.g. Home --> Activity 1 --> Activity 2)
- When press back button, go down one level in the stack
- When press home button, start a new task (stack), back does not navigate to the previous task
- The same activity can be on multiple stacks (e.g., the Camera activity could be part of both Facebook and Twitter app Tasks if you are on a selfie binge)
Fragments
- "Sub-Activity"
- 实现“应用分屏”
- DO NOT depend on any activities
- Reusable (controllers) and Composable
- Have their own layouts, data models, event callbacks, etc.
Life Cycles:
onAttach()
--
Fragment is first “added to” an Activity- onDetach() -- Fragment is "removed from" an Activity
onCreateView()
-- Rendering Fragment View
onActivityCreated()
--
containing Activity’sonCreate()
method has returned, Activity is fully created
Creating Fragments
- Create a class for the fragment, extend PreferenceFragmentCompat