Guides, resources, notes, docs and knowledge for everything Oscar.
Tagshttps://m3.material.io/
Build your first app - Android Basics - Android Developers
Android Developers Blog: Announcing the new guide to Android app modularization
[Coroutine in Android: Basic. Before coroutine, we had to write so… | by Abir Hasan Zoha | AndroidPub | Medium](https://medium.com/@zoha131/coroutine-basic-daf23bbd3c15) |
android:animateLayoutChanges="true"
)Example from Intents and Intent Filters
// Create the text message with a string
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType("text/plain");
// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(sendIntent);
}
https://proandroiddev.com/android-ci-cd-pipeline-with-github-actions-demystifying-github-actions-83258e76a18f
android:launchMode
When up-navigation is present, use singleTop
for the main activity to preserve state when navigating upwards. This will also stop new activites from being started from a notification.
See
Build URLs using Uri.Builder
Use the tools attribute
Frpm Android Studio 3.0, samples are available:
@sample/lorem
onStop()
is calledAn Activity appears in the foreground
onCreate
-> onStart
-> onResume
An Activity is sent to the background (app switched)
onPause
-> onStop
-> onDestroy
From Active to Visible (but not active) (modals)
onPause
-> onResume
From Active or Visible to Background
onPause
-> onStop
-> onRestart
-> onStart
Five ways to persist data in Android:
getDefaultSharedPreferences
getSharedPreferences
onDestroy()
SharedPreferenceChangeListener
is triggered after any value is saved to the SharedPreferences file.PreferenceChangeListener
is triggered before a value is saved to the SharedPreferences file. Because of this, it can prevent an invalid update to a preference. PreferenceChangeListeners are also attached to a single preference.Get permission to use the ContentProvider.
<uses-permission android:name="com.example.appname.TERMS_READ" />
Get the ContentResolver
ContentResolver resolver = getContentResolver();
Cursor cursor = resolver.query(Contract.CONTENT_URI, null, null, null, null);
URI Example:
content://com.example.appname/specificData
CONTENT_URI
Cursor methods arguments
Match integer: #
Match string: *
Example of getType
:
public String getType(@NonNull Uri uri) {
int match = sUriMatcher.match(uri);
switch (match) {
case TASKS:
// directory
return "vnd.android.cursor.dir" + "/" + TaskContract.AUTHORITY + "/" + TaskContract.PATH_TASKS;
case TASK_WITH_ID:
// single item type
return "vnd.android.cursor.item" + "/" + TaskContract.AUTHORITY + "/" + TaskContract.PATH_TASKS;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
}
The best way to asynchronously load data from any ContentProvider is with a CursorLoader
Comparing S09.05-Exercise-MoreDetails…S09.05-Solution-MoreDetails · udacity/ud851-Sunshine
Background task
“More background” than Loader (more front-end)
Loaders outlasts configuration changes
Services outlasts activites
Start a service
Lifecycle:
onDestroy()
[Android: Service, IntentService, AsyncTask and Thread – marsic | dev](http://marsic.info/2016/03/01/android-service-intent-asynctask-thread/) |
Automatically runs on the background thread in order, perfect for one off tasks that need to be handled in the background in order.
Runs on a worker thread (compared to the main thread for a Service).
Stops itself after requests have been handled unlike a Service which needs to be stopped with stopSelf()
or stopService()
“Fire and forget”
Comparing T10.01-Exercise-IntentServices…T10.01-Solution-IntentServices · udacity/ud851-Exercises
Many apps that rely on IntentService do not work properly when targeting Android 8.0 or higher. For this reason, Android Support Library 26.0.0 introduces a new JobIntentService class, which provides the same functionality as IntentService but uses jobs instead of services when running on Android 8.0 or higher.
https://developer.android.com/reference/android/support/v4/app/JobIntentService.html
The base class that handles asynchronous requests that were previously scheduled in a JobScheduler.
Because it runs on the main thread any task needs to be set up on another thread/handler/AsyncTask to avoid blocking future callbacks from the JobManager.
Adding a JobService - YouTube
Exercise: Schedule with FirebaseJobDispatcher - YouTube
It’s important that we verify that we’ve imported jobdispatcher.JobService
rather than the Android framework’s JobService
, because if you do, you’ll definitely have some headaches. Double and triple check that please.
Android Developers Blog: Moar Power in Android 9 Pie and the future
Service required to have a non-dismissible ongoing notification. Less likely to be destroyed when memory gets low.
Example
Driver driver = new GooglePlayDriver(context);
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(driver);
Job myJob = dispatcher.newJobBuilder()
// the JobService that will be called
.setService(MyJobService.class)
// uniquely identifies the job
.setTag("complex-job")
// one-off job
.setRecurring(false)
// don't persist past a device reboot
.setLifetime(Lifetime.UNTIL_NEXT_BOOT)
// start between 0 and 15 minutes (900 seconds)
.setTrigger(Trigger.executionWindow(0, 900))
// overwrite an existing job with the same tag
.setReplaceCurrent(true)
// retry with exponential backoff
.setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
// constraints that need to be satisfied for the job to run
.setConstraints(
// only run on an unmetered network
Constraint.ON_UNMETERED_NETWORK,
// only run when the device is charging
Constraint.DEVICE_CHARGING
)
.build();
Scheduling Jobs - YouTube
The Firebase JobDispatcher
XML
<plurals name="charge_notification_count">
<item quantity="zero">Hydrate while charging reminder sent %d times</item>
<item quantity="one">Hydrate while charging reminder sent %d time</item>
<item quantity="other">Hydrate while charging reminder sent %d times</item>
</plurals>
Java
String formattedChargingReminders = getResources().getQuantityString(R.plurals.charge_notification_count, chargingReminders, chargingReminders);
XML
<string name="format_art_url" translatable="false">https://raw.githubusercontent.com/udacity/Sunshine-Version-2/sunshine_master/app/src/main/res/drawable-xxhdpi/art_<xliff:g id="description">%s</xliff:g>.png</string>
Java
context.getString(R.string.format_art_url, "clear");
Intent in your app designed to be started by another app/service.
This allows a notification (which is handled by the NotificationManager (a system service)) to start your App.
context.getSystemService(Context.NOTIFICATION_SERVICE)
notificationManager.notify(...)
Use a PendingIntent to open your App from a notification.
Notifications - Patterns - Material design guidelines
Notifications - Android Developers
Using Big View Styles - Android Developers
Notification.BigPictureStyle - Android Developers
Engage with rich notifications
Check for Google Play Services both in onCreate() and onResume()
For Android versions >= HONEYCOMB, notifcation image sizes can be found with
int largeIconWidth = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ?
? resources.getDimensionPixelSize(android.R.dimen.notification_large_icon_width)
: resources.getDimensionPixelSize(R.dimen.notification_large_icon_default);
Where R.dimen.notification_large_icon_default
is set to 48dp
Set the color for notifications from Firebase in the manifest with:
<!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
See README(https://goo.gl/l4GJaQ) for more. -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/ic_stat_ic_notification" />
<!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
notification message. See README(https://goo.gl/6BKBk7) for more. -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/colorAccent" />
If the device doesn’t have a compatible version of Google Play services, your app can call GoogleApiAvailability.makeGooglePlayServicesAvailable() to allow users to download Google Play services from the Play Store.
Must use channels once target O is targeted.
System Broadcast Intents - triggers for various device changes.
Creating a broadcast receiever:
To handle broadcasts when app isn’t started: JobDispatcher or in some cases a static broadcast receiver
To handle broadcasts when app is started: dynamic broadcast receiver
Register in onResume() and unregister in onPause if it only is needed for foreground stuff.
Start app
adb shell am start -n com.package.name/com.package.name.ActivityName
Simulate unplugging from USB
adb shell dumpsys battery set usb 0
Above for Android 6.0+
adb shell dumpsys battery unplug
Simulate plugging into power
adb shell dumpsys battery reset
Android Debug Bridge - Android Studio
Avoid nesting view and viewgroups too deep.
General rule of thumb:
Center vertically by putting a top-constraint to the bottom of the other view, and a bottom-constraint to the top of the other view
Captions
@style/TextAppearance.AppCompat.Captiom
Headline
@style/TextAppearance.AppCompat.Display1
Tools > Device monitor > Perspective > Hierarcy viewer
Accessibility settings - display and sound options
contentDescription
on all ImageViews, ImageButtons and Checkboxes
Accessibility Developer Checklist - Android Developers
Localization Checklist - Android Developers
ISO 639-2 Language Code List - Codes for the representation of names of languages (Library of Congress)
Localization checklist - Android Developers
Different views in a RecyclerView
Comparing S11.02-Exercise-TodayListItem…S11.02-Solution-TodayListItem · udacity/ud851-Sunshine
Provide height and width or face the consequences
http://blog.bradcampbell.nz/a-comparison-of-parcelable-boilerplate-libraries/
A theme is a style applied to an activity
For lists, use dimensions such as: @dimen/list_item_icon_margin_right
Use the smallest width qualifier
?attr/listPreferredItemHeight
list_item_selector.xml
Display 4 corresponds to
android:textAppearance="@style/TextAppearance.AppCompat.Display4"
and so on…
Look for support, documentation and functionality
Default toolbar size height: `?attr/actionBarSize”
Style with
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
cardPreventCornerOverlap="false"
Aliases as resources
refs.xml
<resources>
<item type="layout" name="refName">@layout/some_layout</item>
</resources>
https://github.com/udacity/Advanced_Android_Development/compare/6.17_Improving_our_RecyclerView…6.18_Bonus_RecyclerView_Code
Using RecyclerView Part 3 - YouTube
Implementing a modal selection helper for RecyclerView
Scrolling in Parallel - YouTube
Scrolling in Parallel - YouTube
In order to support screen ratios such as 18.5:9 (like that on the Samsung Galaxy S8), add the following to the manifest, in the application element:
_Where ratio_float is the maximum aspect ratio your app can support, expressed as (longer dimension / shorter dimension) in decimal form. _
https://android-developers.googleblog.com/2017/03/update-your-app-to-take-advantage-of.html
Exclude navigation bar and status bar with @android:id/statusBarBackground
and @android:id/navigationBarBackground
respectively.
<item name="android:windowContentTransitions">true</item>
<item name="android:windowEnterTransition">@transition/enter_transition</item>
<item name="android:windowReturnTransition">@transition/return_transition</item>
ActivityOptionsCompat activityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(this);
ActivityCompat.startActivity(this, intent, activityOptions.toBundle());
Animation Resources - Android Developers
The Transitions Framework - Android Developers
Animating Views Using Scenes and Transitions - Android Developers
Applying a Transition - Android Developers
android:transitionName
to view in destinationAdd android:transitionName
to view in origin byt code
ViewCompat.setTransitionName(viewHolder, viewToAnimate, “transitionName”)
Shared Element Transitions (solution) - YouTube
Android Developers Blog: Continuous Shared Element Transitions: RecyclerView to ViewPager
Comparing 8.00_Places_API_Start…8.07_Adding_Attributions · udacity/Advanced_Android_Development
Place Picker - Google Places API for Android - Google Developers
Creating the Widget’s view - YouTube
7.01_Sunshines_First_Widget · udacity/Advanced_Android_Development
SyncAdapter
onHandleIntent()
minResizeWidth
can be set to smaller than default size minWidth
Collection widget: YouTube
Required attributes
Size = 70dp * n - 30dp
= 40 dp for n = 1
= 110 dp = n = 2
public class TodayWidgetProvider extends AppWidgetProvider {
@Override
public void onUpdate(Context context, AppWidgetManager manager, int[} appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
RemoteViews = views = new RemoteViews(context.getPackageName(), R.layot.widget_today_small);
// Clickable widget
Intent intent = new Intent(context, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.widget, pendingIntent);
manager.updateAppWidget(appWidgetId, views);
}
}
}
“Users will complain about performance 3x than any other issue”
Performance Tips - Android Developers
Test overdraw
Manage Your App’s Memory - Android Developers
https://developer.android.com/preview/features/darktheme
Getting context
Fragment#requireContext, for example, returns a non-null Context and throws an IllegalStateException if called when a Context would be null. This way, you can treat the resulting Context as non-null without the need for safe-call operators or workarounds.
Use common Kotlin patterns with Android - Android Developers
Read Fragments: The Solution to (and Cause of) All of Android’s Problems
How Libraries can silently add permissions to your Android App
Android Developers Blog: Android and Architecture
Guide to App Architecture - Android Developers
Same as in Chrome
<manifest>
<meta-data
android:name="android.webkit.WebView.EnableSafeBrowsing"
android:value="true" />
<!-- ... --->
</manifest>
size identifier | size |
---|---|
ldpi | 36x36 |
mdpi | 48x48 |
hdpi | 72x72 |
xhdpi | 96x96 |
xxhdpi | 144x144 |
xxxhdpi | 192x192 |
Google Play | 512x512 |
See http://android-developers.googleblog.com/2017/11/google-play-referrer-api-track-and.html
Android Developers Blog: Discover tools for Android data migration and improve your app retention
Udacity Android Developer Nanodegree - Core App Quality Guidelines
Visual Design and User Interaction
Standard Design
App does not redefine the expected function of a system icon (such as the Back button).
App does not redefine or misuse Android UI patterns, such that icons or behaviors could be misleading or confusing to users.
Navigation
App supports standard system Back button navigation and does not make use of any custom, on-screen "Back button" prompts.
All dialogs are dismissible using the Back button.
Pressing the Home button at any point navigates to the Home screen of the device.
Functionality
Permissions
App does not redefine or misuse Android UI patterns, such that icons or behaviors could be misleading or confusing to users.
App does not request permissions to access sensitive data or services that can cost the user money, unless related to a core capability of the app.
User/App State
App correctly preserves and restores user or app state, that is , student uses a bundle to save app state and restores it via onSaveInstanceState/onRestoreInstanceState. For example,
When a list item is selected, it remains selected on rotation.
When an activity is displayed, the same activity appears on rotation.
User text input is preserved on rotation.
Maintains list items positions on device rotation.
When the app is resumed after the device wakes from sleep (locked) state, the app returns the user to the exact state in which it was last used.
When the app is relaunched from Home or All Apps, the app restores the app state as closely as possible to the previous state.
Performance and Stability
Stability
App does not crash, force close, freeze, or otherwise function abnormally on any targeted device.
Google Play
Content Policies
All content is safe for work content.
App adheres to the Google Play Store App policies.
App’s code follows standard Java/Android Style Guidelines.
80 % Android 7+ (Source:
Single app that supports both mobile and TV devices (i.e. use multiple APK support if needed)
Any TV app activity that is subject to disconnect and reconnect events must be configured to handle reconnection events in the app manifest (Manage TV controllers)
Recommendations channels are only available in Android 8.0 (API level 26) and later. You must use them to supply recommendations for apps running in Android 8.0 (API level 26) and later. To supply recommendations for apps running on earlier versions of Android, your app must use the recommendations row instead.
– Recommend content on the home screen