Pop-up this diagram to its own window |
Troubleshooting Common Mistakes: 20:30 into Class 2, Part 1
of Marko's Bootcamp Mar. 8, 2011, and also in his WEBSITE: ebook. |
Each app launched by the user runs as a separate OS process. A Process is a standard Linux process, one per .APK package.
Each app has its own manifest file to define the permissions it needs and the intents handled by the app.
Intents is a brilliant design that focuses on lower-level tasks (such as writing a note) in a way that users can select different tools (apps) for the same task. loosly couples rather than enables extensibility through plug-ins and reusability.
A Task is the notion of a collection of Activities, each associated with its own UI history stack, capable of spanning several processes. Other apps recognize each task as an application.
An Activity is a "molecule": a discrete chunk of functionality defined by a concrete class in the API. Activities are short-lived, and can be shut down at any time. Each activity encapsulate a particular operation, an execution Context to services, usually optionally associated with a window UI.
Services keep running in the background, independent of any activity.
At run-time, when your Android Java app make requests such as a getContentResolver.query() to access a database or other asset, the Android operating system knows where to route that request to a service which returns, for example, a "cursor" containing data because that service provided its AndroidManifest.xml file which published the "intents" it responds to and the permissions it needs.
A service can also dynamically broadcast intents other components can bind to.
Jar files for external libraries are stored in lib folder and defined as imports in java source code.
REMINDER: Andorid's intents are asynchronous, which means that the app does not wait for a response before doing something else.
Android's synchronous IPC (Inter Process Communication)
Each activity (window) drawn for an app is defined by a layout file such as main.xml, for a main thread which references text variable names such as the hello string. Text values and other controls (aka widgets) displayed on the device are defined in a different strings.xml file within a values folder for each locale supported.
TIP: A layout is usually added for arranging elements in landscape orientation.
Because most graphics cannot scale well, the same image is stored in files of several densities within the res folder, one for high dots-per-inch, one for low, medium, plus others.
The Android OS automatically uses a "Best Match" approach to selecting resources most appropriate for the country, language, device screen size and orientation for each user. If users change their locale to English in the UK, Android will automatically display text from string values in folder values-en-rGB when there is a duplicate string named in the default folder for US english.
Android makes this transparent because custom Java app coding can make locale-neutral references to resource ids (identifiers) such as variable name hello.
During compilation, each resource identifier is associated with a hexadecimal number in a class file named R.java.
The number is held within a string defined with keywords static and final. In the Java language, static defines a single instance of the string for global access by any other class. final means that these string will not be extended.
STAR: At run-time, those pointer values are changed by Android to point to the location of resources approapriate to each user's locale, screen size, orientation, and so forth.
This design means resource files can be updated without recompiling and redeploying the application.
Actual resources are retrieved using a cast operation.
APP:
Gorgeous 1.1 uses Motodev
libraries to present a simple relative layout
that works well across multiple devices.
PhotoDemo:
Simple techniques for creating an
Android UI for multiple devices.
This topic was my second worst area of confusion.
Historically, CSS in HTML was coded to lay elements on screens based on WidthxHeight pixel resolution based on the typical screen size of 1024x768 (XGA) on early monitors (and now iPad tablets). To accomodate various larger screens used by some visitors, many web page designers simply used the smallest common area (such as 640 wide), so that left and right margins are wider for larger monitors.
Even large elements on a smaller screen look tiny on the large screens such as 1920x1080 HDTV sets. And fonts show jagged edges.
On the other extreme, pictures that look normal on regular PC monitors seem overwhelming on handsets of measly 480x320 pixels. So most designers had sent their users to a website separate from the regular website in order to present different layouts to mobile users with small screens and yet another This is an expensive approach, and not sustainable as the variety of screen sizes increases over time.
Sure, images can be scaled. And nine-patch bitmap PNG files can be created to contain SVG support is not complete on browsers. But processing them take CPU cycles.
For standard png and jpg formats, Android provides a naming convention which avoids fixed pixel resolution specifications. Separate files are needed for each major level of detail because even though Internet browsers can scale bitmaps to the width and height specified in the HTML, which results in blurry or pixelated images.
To avoid this, Android recognizes various folder names to specify alternative bitmap resources to display physical screens of different densities.
"Size" | Diagonal Scr. Size | Product | Minimum dip | Icon | Name | dip | Ratio |
---|---|---|---|---|---|---|---|
small | 2 in. | - | 426 x 320 | 36 x 36 | ldpi | 120 | 3 |
normal / medium | 4 in. | - | 470 x 320 | 48 x 48 | mdpi | 160 | 4 |
large | 7 in. | - | 640 x 480 | 72 x 72 | hdpi | 240 | 6 |
xlarge | 10 in. | tablets | 960 x 720 | 96 x 96 | xhdpi | 320 | 8 |
? | - | Galaxy Nexus | 1024x720 | - | - | 316 | - |
- | - | VGA on PCs | 1024x768 | - | - | - | - |
? | 5 in. | HDTV, S4, xperia z | 1920x1080 | - | large-xxhdpi | 441 | - |
Support of each screen type is specified in the Manifest:
<supports-screens android:xlargeScreens="true" android:largeScreens="true" android:normalScreens="true" android:smallScreens="true" android:anyDensity="true" />
Android size names and Java programs coding for it are now being deprecated because, as in our personal life, the concept of what is "normal" and "large" differs.
What needs to happen is a way for code to be written such that screen sizes that we don't know about today will still look good on screen sizes that we don't know about yet appear, and Android should automatically adjust itself from very small to very large screens. This ensures that the beauty of the Golden Ratio is maintained on every size screen.
Android 3.2 introduced Minimum dip widths as the basis for automatic selection of alternate resources. Android selects the size based the actual physical size of an application window, which includes the Options/Action Bar.
But the "dip" unit of measure is not pixels like fixed-length specifications (inches, mm, points) used in absolute layout CSS, but dip (density-independent pixel), aka dp -- abstract units Android invented so it can automatically scale elements appropriately to physical screen size. The scaling is linear:
QUESTION: What happens
on a 240 dpi screen, 1 dip = 1.5 pixel = 1 physical pixel still?
What's the problem with large pixels? Think of you looking down a stadium from a Goodyear blimp, looking at a section where each person held up a should-sized sign over their head to create a group message. Gaps between the signs become more visible as your blimp descends. But if everyone folded their cardboard smaller and then slid together, you would see the same message, but sharper and more life-like.
It may seem reverse logic.
But to accept any old density (rather than Android automatically taking density into account), specify
android:anyDensity = "true"
DPI have recently matured to this point.
WARNING: Images in HTML for iPhone 3GS are constrained to a screen size of 320px × 480px.
Android scales according to the dpi (dots per inch) on screens because biologists tell us that the human retina differentiates detail up to 300 PPI (Pixels Per Inch). Print and web publishers request photographs to be at 300 dpi (dots per inch) for this reason. Digital photographers have long know the combination of dpi and pixels.
dip can also be used to name dimensions for reuse using code such as Resources.getdimen(R.dimen.thin).
<resources> <dimen name="thin">1dip</dimen> ...
Resources should be created to follow UI Guidelines.
This web site follows
Android Brand Guidelines.
The resource types are compiled into a resources.arsc file
Resource type not compiled is the contents of the "raw" folder containing files not applicable to any defined folder (audio clips, CSV flat files, etc.).
To specify font sizes independently, sp (scaled pixels) is used, based on a 10 inch tablet.
Older devices (such as the Archos 5 and signature pads in most supermarkets) had resistive tech which needed pressure from fingernails or styli to manipulate the screen. Newer devices have capacitive tech that depend on moisture on fingertips. This is why special fabric is needed on gloves for smartphones.
TIP: To be finger-friendly, icons to be touched you might want to remain at 32-dpi so that they don't become too small on large screens and too large on small screens.
Launching an app makes it a root of a task.
Eclipse provides tabbed UI to display specific fields in the AndroidManifest.xml file.
An activity is a container holding code that runs an app's UI (screen) a user interacts with (Edit a note or play a game), a focused endeavor the user undertakes.
Each activity's main thread runs all event handlers. An ANR (Application Not Responding) error occurs if an event handler takes more than 5 seconds. An event should be ideally 100ms and no more than 200ms.
New Component Kind include Activity, Service, Broadcast Receiver, and Remote Interface.
Data (name/value pairs) are sent to another device device's XMPP (eXtensible Messaging and Presence Protocol) listener service, just like Gmail servers use.
To indicate to Android Market and the platform that an application requires Android 2.3 or higher:
Within Java code, to invoke features depending on API version:
private static boolean isHoneycomb = android.os.Build.VERSION.SDK_INT > 10; if(!isHoneycomb){ ... }
Why reinvent the wheel? A great way to learn coding is to analyze and leverage code written by experienced coders.
Importing an Android project from GitHub
WEBSITE: Code Project publishes articles (with code) by developers.
This table shows the version application to each sample app that comes with the SDK
described here and within the SDK folder...
\android-sdk\docs\resources\samples\...
Sample Folder | 2.1 7 | 2.2 Froyo 8 | 2.3.4 2.3.3 Gingerbread 10 | 3.0.x Honeycomb 11 | 3.1.x 12 | 3.2 13 | 4.0 14 | 4.0.3 15 |
---|---|---|---|---|---|---|---|---|
AccelerometerPlay | - | - | X | X | X | X | ||
ActionBarCompat | - | - | - | - | - | - | X | X |
AccessibilityService | - | - | X | X | - | - | - | - |
AndroidBeamDemo | - | - | - | - | - | - | X | X |
ApiDemos | X | X | X | X | X | X | ||
BackupRestore | - | X | X | X | X | X | ||
BasicGLSurfaceView | - | - | X | X | X | X | ||
BluetoothChat | X | X | X | X | X | X | X | X |
BluetoothHDP | - | - | - | - | - | - | X | X |
BusinessCard | X | X | X | X | X | X | - | - |
ContactManager | X | X | X | X | X | X | ||
CrossCompatibility | - | - | X | X | X | X | ||
CubeLiveWallpaper | X | X | X | X | X | X | ||
GestureBuilder | X | X | X | X | X | X | ||
Home | X | X | X | X | X | X | ||
HoneycombGallery | - | - | - | X | X | X | ||
JetBoy | X | X | X | X | X | X | ||
LunarLander | X | X | X | X | X | X | ||
MultiResolution | X | X | X | X | X | X | ||
NFCDemo | - | - | X | - | - | - | ||
NotePad | X | X | X | X | X | X | ||
RandomMusicPlayer | - | - | - | - | - | X | ||
RenderScript | - | - | - | - | X | X | ||
Spell Checker Service | - | - | - | - | X | X | 14 | |
Spell Checker Client | - | - | - | - | X | X | 14 | |
RenderScript | - | - | - | - | - | - | X | X |
SampleSyncAdapter | X | X | X | X | X | X | ||
SearchableDictionary | X | X | X | X | X | X | ||
SipDemo | - | - | X | - | X | X | ||
SkeletonApp | X | X | X | X | X | X | ||
Snake | X | X | X | X | X | X | ||
SoftKeyboard [FreeType] | X | X | X | X | X | X | ||
SpellChecker | - | - | - | - | - | - | X | X |
Spinner | - | X | X | X | X | X | ||
SpinnerTest for Activity Testing | - | X | X | X | X | X | ||
StackWidget | - | - | - | - | - | - | ||
TicTacToeLib | - | X | X | X | X | X | ||
TicTacToeMain | - | X | X | X | X | X | ||
ToyVpn | - | - | - | - | - | - | - | X |
TextToSpeech | - | - | - | - | - | 13 | ||
USB | - | - | - | - | X | X | ||
VoicemailProviderDemo | - | - | - | - | - | X | ||
VoiceRecognitionService | - | X | X | X | X | X | - | |
WeatherListWidget | - | - | - | - | X | X | ||
WidgetPreview | - | - | - | X | X | X | ||
WiFiDirectDemo | - | - | - | - | - | - | X | |
Wiktionary | X | X | X | X | X | X | ||
WiktionarySimple | X | X | X | X | X | X | ||
XmlAdapters | - | - | - | X | X | X |
Import the template project into Eclipse: File > Import > Existing Projects into Workspace, click on Select archive file and fill in the path to your copy of script_for_android_template.zip.
http://android.git.kernel.org/?p=platform/packages/apps/Camera.git
andmob.wikidot.com
sample code list.
apps-for-android provides open source Android apps to demonstrate various features of the Android platform.
The Eclipse DDMS (Dalvik Debug Monitor Server) perspective shows threads, memory heap, allocation, and files.
To capture images of what is on the device, first enable the device in Settings > Applications > Development > check USB debugging. Then in the DDMS Device menu, select "Screen capture".
Within the manifest file's "application element, add property android:debuggable="true".
TOOL:
Qualcomm, the maker of the Snapdragon™ chipset running on most Android devices, has a
tool library which includes
Adreno™ Profiler to provide graphics display optimization, per-frame analysis, and real-time performance counter visualization.
You can see the log (including standard Java System.out.print() statements) in the LogCat view, which is part of DDMS view. The "V D I W E" are priorities similar to JLog Verbose (lowest), Debug, Info, Warning, Error, Fatal, Silent (nothing printed). These correspond to logging functions Log.v() Log.d() Log.i() and Log.w().
The java class for logging (named android.util.Log) also outputs log macros from native C applications in liblog.
Since v2.3, when delay policy violations occur. debug by adding (only when in debug mode), to report problems in the main app thread:
StrictMode.enableDefaults();
To send an entry to the debug log (using android.util.log, not org.apache.commons.logging.log):
public class ... extends ... { public static final String TAG = "MyApp1"; ... try { ... } catch (Exception e) { Log.e(TAG, "Unable to get screen density"); e.printStackTrace(); } }
Log documentation and illustration.
To filter log entries using the ADB (Android Device Bridge) shell for StatusActivity only (silence everything else):
TIP: Instead, use RoboGuice's Ln logger so that app name, file and line of the log message, time stamp, thread, and other info is automatically logged. This debug and verbose logging is automatically disabled for release builds. The format and where the logs are written to can be overriden so they can go to a file for crash reporting.
Alternately, just type logcat to invoke logcat.bat in the SDK platform-tools folder after installing
LIB:
Colored Logcat Python Script on Windows
Unlike a modal dialog which takes focus and waits for users to select OK, etc., toasts are small messages that pop up and go away by themselves. Toasts don't take focus away from what the user is doing. In other words, toasts provide "out-of-band" notification to users.
Toasts can be called from the main GUI thread.
However, some prefer to post toast messages to the UI handler thread by calling Context.getMainLooper().
Toast toast = Toast.makeText(NativeContentProvider.this ,R.string.msgWorkHasStarted,Toast.LENGTH_LONG).show();
Toast.LENGTH_LONG is a constant (not a duration like milliseconds, as one would think).
Toast.LENGTH_SHORT is not specified by most developers.
TIP: For flexibility, I prefer to send messages thru my own function in my own package:
MyMessage(User,R.string.msgWorkHasStarted);
static SimpleDateFormat FORMATTER = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
http://www.slideshare.net/motodev/building-quality-into-your-apps-through-testing (Korean)
http://developer.android.com/guide/developing/tools/traceview.html
http://newfoo.net/2009/04/18/performance-tuning-android-applications.html
http://stackoverflow.com/questions/1957135/how-to-test-the-performance-of-an-android-application
STANDARD: Any name can be entered for the trace file name.
CAUTION: Method tracing has a huge impact on performance, so before uploading your application to the market, remove all tracing code from your application.
To obtain permission to write the trace file to your SD Card on the emulator/device, add this to your app's manifest file
Where the app defines its onPause(), onStop(), or onDestroy() methods, add:
In the TraceView bottom Profile panel, each method has its parents (the calling method) and children (called methods).
Look for large percentages or large changes in inclusive % or exclusive % among columns in the Profile Panel :
Once the trace file is on your system drag and drop the trace file on top of traceview.bat in your Android SDK tools folder.
Use Hierarchy View to identify deepest portions of the view hierachy.
Each view level uses memory. So eliminate layers if stack trace shows mostly Android UI rendering code.
On Honeycomb devices (and later), MAT examines HPROF files created by hprof-conv.
In DDMS, select the process and click the heap dump icon (with the red down arrow).
Invoke dumpHprofData() in the android.os.Debug package.
What is not getting garbage collected?
How many objects exist, sizes exist?
Painless Threading
in Android Resources.
RoboGuice IOC (Inversion of Control) Dependency Injection container library created by Google for Android is like the Spring framework. It uses method interception based patterns defined by the AOP (Aspect Oriented Programming) Alliance.
To start with, the latest jars (such as roboguice-1.1.2.jar and roboguice-1.1.2-tests.jar) are added in the build path in Eclipse Project > right-click for Properties > Java Build Path > Libraries > Add External JARs. These are defined in source code as:
import roboguice.activity.RoboActivity; import roboguice.inject.InjectResource; import roboguice.inject.InjectView;
With Guice, we @Inject modules into a running activity Views, Resources, and System Services. This slims down application code. Less code means fewer opportunities for bugs and makes code easier to follow by removing mechanics of the Android platform, and focus on the actual logic unique to the application.
@InjectResource(R.string.app_name) String myName; @Inject public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); name.setText( "Hello, " + myName );
The names of resources Eclipse recognizes are displayed in blue italics.
APP: AstroBoy
This is instead of implementing a factory:
@InjectView private TextView
This is in place of code to find strings from UI object from R.id.mainActivityTextView, then cast them, such as:
TextView textView=(TextView)findViewById(R.id.mainActivityTextView);
TOOL: Android JUnit Report downloads junit report off emulator.
TOOL: Vogar is Google sponsored command-line application to prepares execution code to .java files, .jar files, directories, and class names as arguments to actions. It then executes actions in its own VM. Results are compared to Google's Caliper framework for Java micro-benchmarks at http://microbenchmarks.appspot.com
Ideally, a single testing framework language can be used from unit testing through functional testing through performance testing.
A testing framework should also support continuous integration with utilities such as
TOOL:
Hudson.
Coverage is tracked via
TOOL:
Emma examining Java class files at the Java bytecode level (not JVMPI- or JVMDI level).
Running tests on an Android emulator or device is slow! Building, deploying, and launching the app often takes a minute or more. That’s no way to do TDD.
TOOL: Robotium is like Selenium for web for function, system and acceptance test scenarios, spanning multiple Android activities. Version 1.0 was released January 2010. Its contributor Rena Sreda at JayWay.com
SERVICE:
LessPainful.com tests apps on their
cloud of physical devices
using english-like scripts written in
TOOL:
Cucumber based on Ruby syntax.
APP:
Demo app has a lot of errors to catch.
TOOL: Robospecs works with Specs2 (written in the Scala domain-specific natural language). Built with Maven or sbt (simple build tool for Scala).
The Android API "mock" versions of system classes such as Activity and Context are not true mocks but actually "stubs", and thus cannot verify behavior. So EasyMock can only be used to mock interfaces but not classes.
TOOL:
Roboelectric runs on PC/Mac workstations in an emulator
by intercepting Android class loading and rewriting method bodies with shadow objects that do the test driving.
It runs with EasyMock on PC/Mac JVM.
It was created by people (Pivots) from Pivotal Labs.
Some Googlers (Stephen Ng), on their 20% time, came up with this approach for unit testing:
WEBSITE:
androiddevtesting
demo'd using the Android Notepad Sample app.
To support mocking statics and finals, they use
TOOL:
PowerMock which extends and replaces functions in the EasyMock, JMock, and Mockito frameworks
(instead of jmockit, or jeasytest).
on the Sun JVM.
They use a version of android.jar which does not throw exceptions by builing one by decompiling android.jar and manually removing the exceptions.
AndroidMock (based on EasyMock) runs on Dalvik VM.
Borachio is a mocking framework written in Scala.
TOOL: Monkey & MonkeyRunners
andject example
Marco's
TUTORIAL:
JUnit Test Example
Lar Vogel's
TUTORIAL:
Unit Testing with JUnit and
TUTORIAL:
EasyMock within Eclipse to mock
providers while they are being written.
However, my preference is to avoid
temporary coding and use
external service virtualization.
Auto-generate JUnit code using
TOOL:
Palus which is being merged with
TOOL:
Randoop plugin for Eclipse
After McCabe acquired Agitar in 2008,
free JUnitFactory.com was abandonded
to make room for commercial products
TOOL:
Agitation and
Agitation
"Test-first" approaches to developing code functionality means that the driver is written before the productive program.
Within Eclipse, Run a project As JUnit Test after adding an <Instrumentation> tag within the Mainfest.
<manifest ... <application> <uses-library android:name="android.test.runner" /> ... <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="com.example.app" android:label="Tests for My App" />
This enables you to run using this command line:
In AllTests.java:
package com.example.app; import junit.framework.Test; import junit.framework.TestSuite; import android.test.suitebuilder.TestSuiteBuilder; /** * A test suite containing all tests for my application. */ public class AllTests extends TestSuite { public static Test suite() { return new TestSuiteBuilder(AllTests.class).includeAllPackagesUnderHere().build(); } }
In SomeTest....java, instead of importing standard org.junit.Assert and org.junit.Test:
package com.example.app; import junit.framework.Assert; import android.test.AndroidTestCase; public class SomeTest extends AndroidTestCase { public void testSomething() throws Throwable { Assert.assertTrue(1 + 1 == 2); } }
LIB: Boris Smus' WebIntent Plugin makes it not necessary to create a new plug-in to call an intent, such as:
window.plugins.webintent.startActivity(extras, success, fail);
To send an email:
window.plugins.webintent.startActivity({ action: WebIntent.ACTION_SEND, type: 'text/plain', extras: extras }, function() {}, function() { alert('Failed to send email via Android Intent'); } );
import android.accounts.*;! // needs permission in manifest! // <uses-permission android:name="android.permission.GET_ACCOUNTS" />! // <uses-permission android:name="android.permission.USE_CREDENTIALS" />! AccountManager mgr = AccountManager.get(this);! Account[] acct = mgr.getAccounts();! final int count = accts.length;! for (int i=0; i
Looping Logic
http://stackoverflow.com/questions/7478941/implementing-a-while-loop-in-android
TextView myTextView = (TextView) findViewById(R.id.myTextView); //grab your tv Runnable myRunnable = new Runnable() { @Override public void run() { while (testByte == 0) { Thread.sleep(1000); // Waits for 1 second (1000 milliseconds) String updateWords = updateAuto(); // make updateAuto() return a string myTextView.post(new Runnable() { @Override public void run() { myTextView.setText(updateWords); }); } } };Technical Debt
WIKIPEDIA Technical debt Examples are unit tests, complexity, duplication, design, comments, coding standards and potential problems.
Document code for javadoc generation (like at http://java.sun.com/javase/6/docs/api/).
EXE: Sonar - a continuous inspection engine to manage the technical debt.