[code hl="1, 4, 7"]
TextView textview=findViewById(R.id.textview);
[/code]
Tuesday, July 17, 2018
Chapter 4: TextView
Section 4.1: Spannable TextView
A spannable TextView can be used in Android to highlight a particular portion of text with a different color, style, size, and/or click event in a single TextView widget.
Consider that you have defined a TextView as follows:
Then you can apply different highlighting to it as shown below:
Spannable color: In order to set a different color to some portion of text, a ForegroundColorSpan can be used, as shown in the following example:
[code hl="1, 4, 7"]
Spannable spannable = new SpannableString(firstWord+lastWord);
spannable.setSpan(new ForegroundColorSpan(firstWordColor), 0, firstWord.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan(new ForegroundColorSpan(lastWordColor), firstWord.length(),
firstWord.length()+lastWord.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textview.setText( spannable );
[/code]
Output created by the code above:
Spannable font: In order to set a different font size to some portion of text, a RelativeSizeSpan can be
used, as shown in the following example:
[code hl="1, 4, 7"]
Spannable spannable = new SpannableString(firstWord+lastWord);
spannable.setSpan(new RelativeSizeSpan(1.1f),0, firstWord.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); // set size
spannable.setSpan(new RelativeSizeSpan(0.8f), firstWord.length(), firstWord.length() +
lastWord.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); // set size
textview.setText( spannable );
[/code]
Output created by the code above:
Spannable typeface: In order to set a different font typeface to some portion of text, a custom TypefaceSpan can be used, as shown in the following example:
However, in order to make the above code working, the class CustomTypefaceSpan has to be derived from the class TypefaceSpan. This can be done as follows:
[code hl="1, 4, 7"]
Spannable spannable = new SpannableString(firstWord+lastWord);
spannable.setSpan( new CustomTypefaceSpan("SFUIText-Bold.otf",fontBold), 0,
firstWord.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan( new CustomTypefaceSpan("SFUIText-Regular.otf",fontRegular),
firstWord.length(), firstWord.length() + lastWord.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
text.setText( spannable );
[/code]
[code hl="1, 4, 7"]
family);
newType = type;
}
@Override
public void updateDrawState(TextPaint ds) {
applyCustomTypeFace(ds, newType);
}
@Override
public void updateMeasureState(TextPaint paint) {
applyCustomTypeFace(paint, newType);
}
private static void applyCustomTypeFace(Paint paint, Typeface tf) {
int oldStyle;
Typeface old = paint.getTypeface();
if (old == null) {
oldStyle = 0;
} else {
oldStyle = old.getStyle();
}
int fake = oldStyle & ~tf.getStyle();
if ((fake & Typeface.BOLD) != 0) {
paint.setFakeBoldText(true);
}
if ((fake & Typeface.ITALIC) != 0) {
paint.setTextSkewX(-0.25f);
}
paint.setTypeface(tf);
}
}
[/code]
Section 4.2: Strikethrough TextView
Strikethrough the entire text
[code hl="1, 4, 7"]
String sampleText = "This is a test strike";
textView.setPaintFlags(tv.getPaintFlags()| Paint.STRIKE_THRU_TEXT_FLAG);
textView.setText(sampleText);
[/code]
Strikethrough only parts of the text
[code hl="1, 4, 7"]
String sampleText = "This is a test strike";
SpannableStringBuilder spanBuilder = new SpannableStringBuilder(sampleText);
StrikethroughSpan strikethroughSpan = new StrikethroughSpan();
spanBuilder.setSpan(
strikethroughSpan, // Span to add
0, // Start
4, // End of the span (exclusive)
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE // Text changes will not reflect in the strike changing
);
textView.setText(spanBuilder);
[/code]
Section 4.3: TextView with image
Android allows programmers to place images at all four corners of a TextView. For example, if you are creating a field with a TextView and at same time you want to show that the field is editable, then developers will usually place an edit icon near that field. Android provides us an interesting option called compound drawable for a TextView:
You can set the drawable to any side of your TextView as follows:
Setting the drawable can also be achieved programmatically in the following way:
Setting any of the parameters handed over to setCompoundDrawables() to null will remove the icon from the corresponding side of the TextView.
Section 4.3: TextView with image
Android allows programmers to place images at all four corners of a TextView. For example, if you are creating a field with a TextView and at same time you want to show that the field is editable, then developers will usually place an edit icon near that field. Android provides us an interesting option called compound drawable for a TextView:
[code hl="1, 4, 7"]
[/code]
You can set the drawable to any side of your TextView as follows:
[code hl="1, 4, 7"]
android:drawableLeft="@drawable/edit"
android:drawableRight="@drawable/edit"
android:drawableTop="@drawable/edit"
android:drawableBottom="@drawable/edit"
[/code]
Setting the drawable can also be achieved programmatically in the following way:
[code hl="1, 4, 7"]
yourTextView.setCompoundDrawables(leftDrawable, rightDrawable, topDrawable, bottomDrawable);
[/code]
Setting any of the parameters handed over to setCompoundDrawables() to null will remove the icon from the corresponding side of the TextView.
Section 4.4: Make RelativeSizeSpan align to top
In order to make a RelativeSizeSpan align to the top, a custom class can be derived from the class
SuperscriptSpan. In the following example, the derived class is named TopAlignSuperscriptSpan:
activity_main.xml:
[code hl="1, 4, 7"]
[/code]
MainActivity.java:
[code hl="1, 4, 7"]
TextView txtView = (TextView) findViewById(R.id.txtView);
SpannableString spannableString = new SpannableString("RM123.456");
spannableString.setSpan( new TopAlignSuperscriptSpan( (float)0.35 ), 0, 2,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE );
txtView.setText(spannableString);
[/code]
TopAlignSuperscriptSpan.java:
[code hl="1, 4, 7"]
private class TopAlignSuperscriptSpan extends SuperscriptSpan {
//divide superscript by this number
protected int fontScale = 2;
//shift value, 0 to 1.0
protected float shiftPercentage = 0;
//doesn't shift
TopAlignSuperscriptSpan() {}
//sets the shift percentage
TopAlignSuperscriptSpan( float shiftPercentage ) {
if( shiftPercentage > 0.0 && shiftPercentage < 1.0 )
this.shiftPercentage = shiftPercentage;
}
@Override
public void updateDrawState( TextPaint tp ) {
//original ascent
float ascent = tp.ascent();
//scale down the font
tp.setTextSize( tp.getTextSize() / fontScale );
//get the new font ascent
float newAscent = tp.getFontMetrics().ascent;
//move baseline to top of old font, then move down size of new font
//adjust for errors with shift percentage
tp.baselineShift += ( ascent - ascent * shiftPercentage )
- (newAscent - newAscent * shiftPercentage );
}
@Override
public void updateMeasureState( TextPaint tp ) {
updateDrawState( tp );
}
}
[/code]
Reference screenshot:
Section 4.5: Pinchzoom on TextView
activity_main.xml:
[code hl="1, 4, 7"]
[/code]
MainActivity.java:
[code hl="1, 4, 7"]
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.TextView;
public class MyTextViewPinchZoomClass extends Activity implements OnTouchListener {
final static float STEP = 200;
TextView mytv;
float mRatio = 1.0f;
int mBaseDist;
float mBaseRatio;
float fontsize = 13;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mytv = (TextView) findViewById(R.id.mytv);
mytv.setTextSize(mRatio + 13);
}
public boolean onTouchEvent(MotionEvent event) {
if (event.getPointerCount() == 2) {
int action = event.getAction();
int pureaction = action & MotionEvent.ACTION_MASK;
if (pureaction == MotionEvent.ACTION_POINTER_DOWN) {
mBaseDist = getDistance(event);
mBaseRatio = mRatio;
} else {
float delta = (getDistance(event) - mBaseDist) / STEP;
float multi = (float) Math.pow(2, delta);
mRatio = Math.min(1024.0f, Math.max(0.1f, mBaseRatio * multi));
mytv.setTextSize(mRatio + 13);
}
}
return true;
}
int getDistance(MotionEvent event) {
int dx = (int) (event.getX(0) - event.getX(1));
int dy = (int) (event.getY(0) - event.getY(1));
return (int) (Math.sqrt(dx * dx + dy * dy));
}
public boolean onTouch(View v, MotionEvent event) {
return false;
}
}
[/code]
Section 4.6: Textview with different Textsize
You can archive different Textsizes inside a Textview with a Span
[code hl="1, 4, 7"]
TextView textView = (TextView) findViewById(R.id.textView);
Spannable span = new SpannableString(textView.getText());
span.setSpan(new RelativeSizeSpan(0.8f), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(span)
[/code]
Monday, July 16, 2018
Chapter 3: Instant Run in Android Studio
Section 3.1: Enabling or disabling Instant Run
1. Open the Settings or Preferences dialog:
- On Windows or Linux, select File > Settings from the main menu.
- On Mac OSX, select Android Studio > Preferences from the main menu.
2. Navigate to Build, Execution, Deployment > Compiler.
3. In the text field next to Command-line Options, enter your command-line options.
4. Click OK to save and exit.
The top option is Instant run. Check/uncheck that box.
Section 3.2: Types of code Swaps in Instant Run
There are three types of code swaps that Instant run enables to support faster debugging and running app from your code in Android Studio.
- Hot Swap
- Warm Swap
- Cold Swap
When are each of these swaps triggered?
- HOT SWAP is triggered when an existing method's implementation is changed.
- WARM SWAP is triggered when an existing resource is changed or removed (anything in the res folder)
- COLD SWAP whenever there is a structural code change in your app's code e.g.
1. Add, remove, or change:
- an annotation
- an instance field
- a static field
- a static method signature
- an instance method signature
2. Change which parent class the current class inherits from3. Change the list of implemented interfaces4. Change a class's static initializer5. Reorder layout elements that use dynamic resource IDs
What happens when a code swap happens?
- HOT SWAP changes are visible instantly - as soon as the next call to the method whose implementation is changed is made.
- WARM SWAP restarts the current activity
- COLD SWAP restarts the entire app (without reinstall)
Section 3.3: Unsupported code changes when using Instant Run
There are a few changes where instant won't do its trick and a full build and reinstall fo your app will happen just like it used to happen before Instant Run was born.
1. Change the app manifest
2. Change resources referenced by the app manifest
3. Change an Android widget UI element (requires a Clean and Rerun)
Chapter 2: Android Studio
Section 2.1: Setup Android Studio
System Requirements
- Microsoft® Windows® 8/7/Vista/2003 (32 or 64-bit).
- Mac® OS X® 10.8.5 or higher, up to 10.9 (Mavericks)
- GNOME or KDE desktop
Installation
Window
1. Download and install JDK (Java Development Kit) version 8
2. Download Android Studio
3. Launch Android Studio.exe then mention JDK path and download the latest SDK
Linux
1. Download and install JDK (Java Development Kit) version 8
2. Download Android Studio
3. Extract the zip file
4. Open terminal, cd to the extracted folder, cd to bin (example cd android-studio/bin)
5. Run ./studio.sh
Section 2.2: View And Add Shortcuts in Android Studio
By going to Settings >> Keymap A window will popup showing All the Editor Actions with the their name and shortcuts. Some of the Editor Actions do not have shortcuts. So right click on that and add a new shortcut to that.
Check the image below
Section 2.3: Android Studio useful shortcuts
The following are some of the more common/useful shortcuts.
These are based on the default IntelliJ shortcut map. You can switch to other common IDE shortcut maps via File -> Settings -> Keymap -> <Choose Eclipse/Visual Studio/etc from Keymaps dropdown>
| Action | Shortcut |
| Format code | CTRL + ALT + L |
| Add unimplemented methods | CTRL + I |
| Show logcat | ALT + 6 |
| Build | CTRL + F9 |
| Build and Run | CTRL + F10 |
| Find | CTRL + F |
| Find in project | CTRL + SHIFT + F |
| Find and replace | CTRL + R |
| Find and replace in project | CTRL + SHIFT + R |
| Override methods | CTRL + O |
| Show project | ALT + 1 |
| Hide project - logcat | SHIFT + ESC |
| Collapse all | CTRL + SHIFT + NumPad + |
| View Debug Points | CTRL + SHIFT + F8 |
| Expand all | CTRL + SHIFT + NumPad - |
| Open Settings | ALT + s |
| Select Target (open current file in Project view) | ALT + F1 → ENTER |
| Search Everywhere | SHIFT → SHIFT (Double shift) |
| Code | Surround With | CTRL → ALT + T |
| Create method form selected code | ALT + CTRL |
Refactor:
| Action | Shortcut |
| Refactor This (menu/picker for all applicable refactor actions of the current element) | Mac CTRL + T - Win/Linux CTRL + ALT + T |
| Rename | SHIFT + F6 |
| Extract Method | Mac CMD + ALT + M - Win/Linux CTRL + ALT + M |
| Extract Parameter | Mac CMD + ALT + P - Win/Linux CTRL + ALT + P |
| Extract Variable | Mac CMD + ALT + V - Win/Linux CTRL + ALT + V |
Section 2.4: Android Studio Improve performance tip
Enable Offline Work:
1. Click File -> Settings. Search for "gradle" and click in Offline work box.
2. Go to Compiler (in same settings dialog just below Gradle) and add --offline to Command-line Options text box.
Improve Gradle Performance
Add following two line of code in your gradle.properties file.
[code hl="1, 4, 7"]
org.gradle.daemon=true
org.gradle.parallel=true
[/code]
Increasing the value of -Xmx and -Xms in studio.vmoptions file
[code hl="1, 4, 7"]
-Xms1024m
-Xmx4096m
-XX:MaxPermSize=1024m
-XX:ReservedCodeCacheSize=256m
-XX:+UseCompressedOops
[/code]
Window
[code hl="1, 4, 7"]
%USERPROFILE%.{FOLDER_NAME}\studio.exe.vmoptions and/or
%USERPROFILE%.{FOLDER_NAME}\studio64.exe.vmoptions
[/code]
Mac
[code hl="1, 4, 7"]
~/Library/Preferences/{FOLDER_NAME}/studio.vmoptions
[/code]
Linux
~/.{FOLDER_NAME}/studio.vmoptions and/or ~/.{FOLDER_NAME}/studio64.vmoptions
Section 2.5: Gradle build project takes forever
Android Studio -> Preferences -> Gradle -> Tick Offline work and then restart your Android studio.
Reference screenshot:
Section 2.6: Enable/Disable blank line copy
ctrl + alt + shift + / (cmd + alt + shift + / on MacOS) should show you the following dialog:
Clicking on Registry you will get
The key you want to enable/disable is
[code hl="1, 4, 7"]
editor.skip.copy.and.cut.for.empty.selection
[/code]
Tested on Linux Ubuntu and MacOS.
Section 2.7: Custom colors of logcat message based on message importance
Go to File -> Settings -> Editor -> Colors & Fonts -> Android Logcat
Change the colors as you need:
Choose the appropriate color:
Section 2.8: Filter logs from UI
Android logs can be filtered directly from the UI. Using this code
[code hl="1, 4, 7"]
public class MainActivity extends AppCompatActivity {
private final static String TAG1 = MainActivity.class.getSimpleName();
private final static String TAG2 = MainActivity.class.getCanonicalName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e(TAG1,"Log from onCreate method with TAG1");
Log.i(TAG2,"Log from onCreate method with TAG2");
}
}
[/code]
If I use the regex TAG1|TAG2 and the level verbose I get
[code hl="1, 4, 7"]
01-14 10:34:46.961 12880-12880/android.doc.so.thiebaudthomas.sodocandroid E/MainActivity: Log from
onCreate method with TAG1
01-14 10:34:46.961 12880-12880/android.doc.so.thiebaudthomas.sodocandroid
I/androdi.doc.so.thiebaudthomas.sodocandroid.MainActivity: Log from onCreate method with TAG2
[/code]
The level can be set to get logs with given level and above. For example the verbose level will catch verbose, debug, info, warn, error and assert logs.
Using the same example, if I set the level to error, I only get
[code hl="1, 4, 7"]
01-14 10:34:46.961 12880-12880/androdi.doc.so.thiebaudthomas.sodocandroid E/MainActivity: Log from
onCreate method with TAG1
[/code]
Section 2.9: Create filters configuration
Custom filters can be set and save from the UI. In the AndroidMonitor tab, click on the right dropdown (must contains Show only selected application or No filters) and select Edit filter configuration.
And use it (you can selected it from the same dropdown)
Important If you add an input in the filter bar, android studio will consider both your filter and your input.
With both input and filter there is no output
Without filter, there is some outputs
Sunday, July 15, 2018
Chapter 1: Getting started with Android
Section 1.1: Creating a New Project
Set up Android Studio
Start by setting up Android Studio and then open it. Now, you're ready to make your first Android App!
Note: this guide is based on Android Studio 2.2, but the process on other versions is mainly the same.
Configure Your Project
Basic Configuration
You can start a new project in two ways:
- Click Start a New Android Studio Project from the welcome screen.
- Navigate to File → New Project if you already have a project open.
Next, you need to describe your application by filling out some fields:
1. Application Name - This name will be shown to the user.
Example: Hello World. You can always change it later in AndroidManifest.xml file.
2. Company Domain - This is the qualifier for your project's package name.
Example: mycompany.com
3. Package Name (aka applicationId) - This is the fully qualified project package name.
It should follow Reverse Domain Name Notation (aka Reverse DNS): Top Level Domain . Company Domain .
[Company Segment .] Application Name.
Example: com.mycompany.android.helloworld or com.mycompany.helloworld. You can always
change your applicationId by overriding it in your gradle file.
Don't use the default prefix "com.example" unless you don't intend to submit your application to the
Google Play Store. The package name will be your unique applicationId in Google Play.
4. Project Location - This is the directory where your project will be stored.
Select Form Factors and API Level
The next window lets you select the form factors supported by your app, such as phone, tablet, TV, Wear, and Google Glass. The selected form factors become the app modules within the project. For each form factor, you can also select the API Level for that app. To get more information, click Help me choose
![]() |
| Chart of the current Android version distributions, shown when you click Help me choose. |
The Android Platform Distribution window shows the distribution of mobile devices running each version of Android, as shown in Figure 2. Click on an API level to see a list of features introduced in the corresponding version of Android. This helps you choose the minimum API Level that has all the features that your apps needs, so you can reach as many devices as possible. Then click OK.
Now, choose what platforms and version of Android SDK the application will support.
For now, select only Phone and Tablet.
The Minimum SDK is the lower bound for your app. It is one of the signals the Google Play Store uses to determine which devices an app can be installed on. For example, Stack Exchange's app supports Android 4.1+.
Android Studio will tell you (approximately) what percentage of devices will be supported given the specified minimum SDK.
Lower API levels target more devices but have fewer features available.
When deciding on the Minimum SDK, you should consider the Dashboards stats, which will give you version information about the devices that visited the Google Play Store globally in the last week.
Add an activity
Now we are going to select a default activity for our application. In Android, an Activity is a single screen that will be presented to the user. An application can house multiple activities and navigate between them. For this example, choose Empty Activity and click next.
Here, if you wish, you can change the name of the activity and layout. A good practice is to keep Activity as a suffix for the activity name, and activity_ as a prefix for the layout name. If we leave these as the default, Android Studio will generate an activity for us called MainActivity, and a layout file called activity_main. Now click Finish.
Android Studio will create and configure our project, which can take some time depending on the system.
Inspecting the Project
To understand how Android works, let's take a look at some of the files that were created for us.
On the left pane of Android Studio, we can see the structure of our Android application.
First, let's open AndroidManifest.xml by double clicking it. The Android manifest file describes some of the basic information about an Android application. It contains the declaration of our activities, as well as some more advanced components.
If an application needs access to a feature protected by a permission, it must declare that it requires that permission with a <uses-permission> element in the manifest. Then, when the application is installed on the device, the installer determines whether or not to grant the requested permission by checking the authorities that signed the application's certificates and, in some cases, asking the user. An application can also protect its own components (activities, services, broadcast receivers, and content providers) with permissions. It can employ any of the permissions defined by Android (listed in android.Manifest.permission) or declared by other applications. Or it can define its own.
Next, let's open activity_main.xml which is located in app/src/main/res/layout/. This file contains declarations for the visual components of our MainActivity. You will see visual designer. This allows you to drag and drop elements onto the selected layout.
You can also switch to the xml layout designer by clicking "Text" at the bottom of Android Studio, as seen here:
You will see a widget called a TextView inside of this layout, with the android:text property set to "Hello World!". This is a block of text that will be shown to the user when they run the application.
You can read more about Layouts and attributes.
Next, let's take a look at MainActivity. This is the Java code that has been generated for MainActivity.
As defined in our Android manifest, MainActivity will launch by default when a user starts the HelloWorld app.
Lastly, open up the file named build.gradle located in app/.
Android Studio uses the build system Gradle to compile and build Android applications and libraries.
compileSdkVersion
compileSdkVersion is your way to tell Gradle what version of the Android SDK to compile your app with. Using the new Android SDK is a requirement to use any of the new APIs added in that level.
It should be emphasized that changing your compileSdkVersion does not change runtime behavior. While new compiler warnings/errors may be present when changing your compileSdkVersion, your compileSdkVersion is not included in your APK: it is purely used at compile time.
Therefore it is strongly recommended that you always compile with the latest SDK. You’ll get all the benefits of new compilation checks on existing code, avoid newly deprecated APIs, and be ready to use new APIs.
minSdkVersion
If compileSdkVersion sets the newest APIs available to you, minSdkVersion is the lower bound for your app. The minSdkVersion is one of the signals the Google Play Store uses to determine which of a user’s devices an app can be installed on.
It also plays an important role during development: by default lint runs against your project, warning you when you use any APIs above your minSdkVersion, helping you avoid the runtime issue of attempting to call an API that doesn’t exist. Checking the system version at runtime is a common technique when using APIs only on newer platform versions.
targetSdkVersion
targetSdkVersion is the main way Android provides forward compatibility by not applying behavior changes unless the targetSdkVersion is updated. This allows you to use new APIs prior to working through the behavior changes.
Updating to target the latest SDK should be a high priority for every app. That doesn’t mean you have to use every new feature introduced nor should you blindly update your targetSdkVersion without testing.
targetSDKVersion is the version of Android which is the upper-limit for the available tools. If targetSDKVersion is less than 23, the app does not need to request permissions at runtime for an instance, even if the app is being run on API 23+. TargetSDKVersion does not prevent android versions above the picked Android version from running the app.
You can find more info about the Gradle plugin:
- A basic example
- Introduction to the Gradle plugin for android and the wrapper
- Introduction to the configuration of the build.gradle and the DSL methods
Running the Application
Now, let's run our HelloWorld application. You can either run an Android Virtual Device (which you can set up by using the AVD Manager in Android Studio, as described in the example below) or connect your own Android device through a USB cable.
Setting up an Android device
To run an application from Android Studio on your Android Device, you must enable USB Debugging in the Developer Options in the settings of your device.
Settings > Developer options > USB debugging
If Developer Options is not visible in the settings, navigate to About Phone and tap on the Build Number seven times. This will enable Developer Options to show up in your settings.
Settings > About phone > Build number
You also might need to change build.gradle configuration to build on a version that your device has.
Running from Android Studio
Click the green Run button from the toolbar at the top of Android Studio. In the window that appears, select whichever device you would like to run the app on (start an Android Virtual Device if necessary, or see Setting up an AVD (Android Virtual Device) if you need to set one up) and click OK.
On devices running Android 4.4 (KitKat) and possibly higher, a pop-up will be shown to authorize USB debugging. Click OK to accept.
The application will now install and run on your Android device or emulator.
APK file location
When you prepare your application for release, you configure, build, and test a release version of your application. The configuration tasks are straightforward, involving basic code cleanup and code modification tasks that help optimize your application. The build process is similar to the debug build process and can be done using JDK and Android SDK tools. The testing tasks serve as a final check, ensuring that your application performs as expected under real-world conditions. When you are finished preparing your application for release you have a signed APK file, which you can distribute directly to users or distribute through an application marketplace such as Google Play.
Android Studio
Since in the above examples Gradle is used, the location of the generated APK file is:
<Your Project Location>/app/build/outputs/apk/app-debug.apk
IntelliJ
If you are a user of IntelliJ before switching to Studio, and are importing your IntelliJ project directly, then nothing changed. The location of the output will be the same under:
out/production/...
Note: this is will become deprecated sometimes around 1.0
Eclipse
If you are importing Android Eclipse project directly, do not do this! As soon as you have dependencies in your project (jars or Library Projects), this will not work and your project will not be properly setup. If you have no dependencies, then the apk would be under the same location as you'd find it in Eclipse:
bin/...
Section 1.2: Setting up Android Studio
Android Studio is the Android development IDE that is officially supported and recommended by Google. Android Studio comes bundled with the Android SDK Manager, which is a tool to download the Android SDK components required to start developing apps.
Installing Android Studio and Android SDK tools:
- Download and install Android Studio.
- Download the latest SDK Tools and SDK Platform-tools by opening the Android Studio, and then following the Android SDK Tool Updates instructions. You should install the latest available stable packages.
If you need to work on old projects that were built using older SDK versions, you may need to download these versions as well.
Since Android Studio 2.2, a copy of the latest OpenJDK comes bundled with the install and is the recommended JDK (Java Development Kit) for all Android Studio projects. This removes the requirement of having Oracle's JDK package installed. To use the bundled SDK, proceed as follows;
- Open your project in Android Studio and select File > Project Structure in the menu bar.
- In the SDK Location page and under JDK location, check the Use embedded JDK checkbox.
- Click OK.
Configure Android Studio
Android Studio provides access to two configuration files through the Help menu:
- studio.vmoptions: Customize options for Studio's Java Virtual Machine (JVM), such as heap size and cache size. Note that on Linux machines this file may be named studio64.vmoptions, depending on your version of Android Studio.
- idea.properties: Customize Android Studio properties, such as the plugins folder path or maximum supported file size.
Change/add theme
You can change it as your preference. File->Settings->Editor->Colors & Fonts-> and select a theme. Also you can download new themes from http://color-themes.com/ Once you have downloaded the .jar.zip file, go to File -> Import Settings... and choose the file downloaded.
Compiling Apps
Create a new project or open an existing project in Android Studio and press the green Play button on the top toolbar to run it. If it is gray you need to wait a second to allow Android Studio to properly index some files, the progress of which can be seen in the bottom status bar.
If you want to create a project from the shell make sure that you have a local.properties file, which is created by Android Studio automatically. If you need to create the project without Android Studio you need a line starting with sdk.dir= followed by the path to your SDK installation.
Open a shell and go into the project's directory. Enter ./gradlew aR and press enter. aR is a shortcut for assembleRelease, which will download all dependencies for you and build the app. The final APK file will be in ProjectName/ModuleName/build/outputs/apk and will been called ModuleName-release.apk.
Section 1.3: Android programming without an IDE
This is a minimalist Hello World example that uses only the most basic Android tools.
Requirements and assumptions
- Oracle JDK 1.7 or later
- Android SDK Tools (just the command line tools)
This example assumes Linux. You may have to adjust the syntax for your own platform.
Setting up the Android SDK
After unpacking the SDK release:
- Install additional packages using the SDK manager. Don't use android update sdk --no-ui as instructed in the bundled Readme.txt; it downloads some 30 GB of unnecessary files. Instead use the interactive SDK manager android sdk to get the recommended minimum of packages.
- Append the following JDK and SDK directories to your execution PATH. This is optional, but the instructions below assume it:
- JDK/bin
- SDK/platform-tools
- SDK/tools
- SDK/build-tools/LATEST (as installed in step 1)
- Create an Android virtual device. Use the interactive AVD Manager (android avd). You might have to fiddle a bit and search for advice; the on-site instructions aren't always helpful. (You can also use your own device)
- Run the device: emulator -avd DEVICE.
- If the device screen appears to be locked, then swipe to unlock it.
- Leave it running while you code the app.
Coding the app
0. Change to an empty working directory.
1. Make the source file:
[code hl="1, 4, 7"]
mkdir --parents src/dom/domain
touch src/dom/domain/SayingHello.java
[/code]
Content:
[code hl="1, 4, 7"]
package dom.domain;
import android.widget.TextView;
public final class SayingHello extends android.app.Activity
{
protected @Override void onCreate( final android.os.Bundle activityState )
{
super.onCreate( activityState );
final TextView textV = new TextView( SayingHello.this );
textV.setText( "Hello world" );
setContentView( textV );
}
}
[/code]
2. Add a manifest:
[code hl="1, 4, 7"]
touch AndroidManifest.xml
[/code]
Content:
[code hl="1, 4, 7"]
[/code]
3. Make a sub-directory for the declared resources:
[code hl="1, 4, 7"]
mkdir res
[/code]
Leave it empty for now.
Building the code
0. Generate the source for the resource declarations. Substitute here the correct path to your SDK, and the
installed API to build against (e.g. "android-23"):
Resource declarations (described further below) are actually optional. Meantime the above call does nothing
if res/ is still empty.
1. Compile the source code to Java bytecode (.java → .class):
2. Translate the bytecode from Java to Android (.class → .dex):
First using Jill (.class → .jayce):
Then Jack (.jayce → .dex):
Android bytecode used to be called "Dalvik executable code", and so "dex".
You could replace steps 11 and 12 with a single call to Jack if you like; it can compile directly from Java source (.java → .dex). But there are advantages to compiling with javac. It's a better known, better documented and more widely applicable tool.
3. Package up the resource files, including the manifest:
That results in a partial APK file (Android application package).
4. Make the full APK using the ApkBuilder tool:
[code hl="1, 4, 7"] java -classpath SDK/tools/lib/sdklib.jar \\ com.android.sdklib.build.ApkBuilderMain \\ app.apkUnalign \\ -d -f classes.dex -v -z app.apkPart [/code]
It warns, "THIS TOOL IS DEPRECATED. See --help for more information." If --help fails with an ArrayIndexOutOfBoundsException, then instead pass no arguments:
[code hl="1, 4, 7"] java -classpath SDK/tools/lib/sdklib.jar \\ com.android.sdklib.build.ApkBuilderMain [/code]
It explains that the CLI (ApkBuilderMain) is deprecated in favour of directly calling the Java API (ApkBuilder). (If you know how to do that from the command line, please update this example.)
5. Optimize the data alignment of the APK (recommended practice):
[code hl="1, 4, 7"] zipalign -f -v 4 app.apkUnalign app.apk [/code]
Installing and running
0. Install the app to the Android device:
[code hl="1, 4, 7"] adb install -r app.apk [/code]
1. Start the app:
[code hl="1, 4, 7"] adb shell am start -n dom.domain/.SayingHello [/code]
It should run and say hello.
That's all. That's what it takes to say hello using the basic Android tools.
Declaring a resource
This section is optional. Resource declarations aren't required for a simple "hello world" app. If they aren't required for your app either, then you could streamline the build somewhat by omitting step 10, and removing the reference to the res/ directory from step 13.
Otherwise, here's a brief example of how to declare a resource, and how to reference it.
0. Add a resource file:
[code hl="1, 4, 7"] mkdir res/values touch res/values/values.xml [/code]
Content:
[code hl="1, 4, 7"]
Saying hello
[/code]
1. Reference the resource from the XML manifest. This is a declarative style of reference:
[code hl="1, 4, 7"]
[/code]
2. Reference the same resource from the Java source. This is an imperative reference:[code hl="1, 4, 7"] // v.setText( "Hello world" ); v.setText( "This app is called " + getResources().getString( R.string.appLabel )); [/code]
3. Test the above modifications by rebuilding, reinstalling and re-running the app (steps 10-17). It should restart and say, "This app is called Saying hello".
Uninstalling the app
[code hl="1, 4, 7"] adb uninstall dom.domain [/code]
Section 1.4: Application Fundamentals
Android Apps are written in Java. The Android SDK tools compile the code, data and resource files into an APK (Android package). Generally, one APK file contains all the content of the app.
Each app runs on its own virtual machine(VM) so that app can run isolated from other apps. Android system works with the principle of least privilege. Each app only has access to the components which it requires to do its work, and no more. However, there are ways for an app to share data with other apps, such as by sharing Linux user id between app, or apps can request permission to access device data like SD card, contacts etc.
App Components
App components are the building blocks of an Android app. Each components plays a specific role in an Android app which serves a distinct purpose and has distinct life-cycles(the flow of how and when the component is created and destroyed). Here are the four types of app components:
Building the code
0. Generate the source for the resource declarations. Substitute here the correct path to your SDK, and the
installed API to build against (e.g. "android-23"):
[code hl="1, 4, 7"]
aapt package -f \\
-I SDK/platforms/android-API/android.jar \\
-J src -m \\
-M AndroidManifest.xml -S res -v
[/code]
Resource declarations (described further below) are actually optional. Meantime the above call does nothing
if res/ is still empty.
1. Compile the source code to Java bytecode (.java → .class):
[code hl="1, 4, 7"]
javac \\
-bootclasspath SDK/platforms/android-API/android.jar \\
-classpath src -source 1.7 -target 1.7 \\
src/dom/domain/*.java
[/code]
2. Translate the bytecode from Java to Android (.class → .dex):
First using Jill (.class → .jayce):
[code hl="1, 4, 7"]
java -jar SDK/build-tools/LATEST/jill.jar \\
--output classes.jayce src
[/code]
Then Jack (.jayce → .dex):
[code hl="1, 4, 7"]
java -jar SDK/build-tools/LATEST/jack.jar \\
--import classes.jayce --output-dex .
[/code]
Android bytecode used to be called "Dalvik executable code", and so "dex".
You could replace steps 11 and 12 with a single call to Jack if you like; it can compile directly from Java source (.java → .dex). But there are advantages to compiling with javac. It's a better known, better documented and more widely applicable tool.
3. Package up the resource files, including the manifest:
[code hl="1, 4, 7"]
aapt package -f \\
-F app.apkPart \\
-I SDK/platforms/android-API/android.jar \\
-M AndroidManifest.xml -S res -v
[/code]
That results in a partial APK file (Android application package).
4. Make the full APK using the ApkBuilder tool:
[code hl="1, 4, 7"] java -classpath SDK/tools/lib/sdklib.jar \\ com.android.sdklib.build.ApkBuilderMain \\ app.apkUnalign \\ -d -f classes.dex -v -z app.apkPart [/code]
It warns, "THIS TOOL IS DEPRECATED. See --help for more information." If --help fails with an ArrayIndexOutOfBoundsException, then instead pass no arguments:
[code hl="1, 4, 7"] java -classpath SDK/tools/lib/sdklib.jar \\ com.android.sdklib.build.ApkBuilderMain [/code]
It explains that the CLI (ApkBuilderMain) is deprecated in favour of directly calling the Java API (ApkBuilder). (If you know how to do that from the command line, please update this example.)
5. Optimize the data alignment of the APK (recommended practice):
[code hl="1, 4, 7"] zipalign -f -v 4 app.apkUnalign app.apk [/code]
Installing and running
0. Install the app to the Android device:
[code hl="1, 4, 7"] adb install -r app.apk [/code]
1. Start the app:
[code hl="1, 4, 7"] adb shell am start -n dom.domain/.SayingHello [/code]
It should run and say hello.
That's all. That's what it takes to say hello using the basic Android tools.
Declaring a resource
This section is optional. Resource declarations aren't required for a simple "hello world" app. If they aren't required for your app either, then you could streamline the build somewhat by omitting step 10, and removing the reference to the res/ directory from step 13.
Otherwise, here's a brief example of how to declare a resource, and how to reference it.
0. Add a resource file:
[code hl="1, 4, 7"] mkdir res/values touch res/values/values.xml [/code]
Content:
[code hl="1, 4, 7"]
1. Reference the resource from the XML manifest. This is a declarative style of reference:
[code hl="1, 4, 7"]
2. Reference the same resource from the Java source. This is an imperative reference:[code hl="1, 4, 7"] // v.setText( "Hello world" ); v.setText( "This app is called " + getResources().getString( R.string.appLabel )); [/code]
3. Test the above modifications by rebuilding, reinstalling and re-running the app (steps 10-17). It should restart and say, "This app is called Saying hello".
Uninstalling the app
[code hl="1, 4, 7"] adb uninstall dom.domain [/code]
Each app runs on its own virtual machine(VM) so that app can run isolated from other apps. Android system works with the principle of least privilege. Each app only has access to the components which it requires to do its work, and no more. However, there are ways for an app to share data with other apps, such as by sharing Linux user id between app, or apps can request permission to access device data like SD card, contacts etc.
App Components
App components are the building blocks of an Android app. Each components plays a specific role in an Android app which serves a distinct purpose and has distinct life-cycles(the flow of how and when the component is created and destroyed). Here are the four types of app components:
- Activities: An activity represents a single screen with a User Interface(UI). An Android app may have more than one activity. (e.g. an email app might have one activity to list all the emails, another to show the contents of each email, and another to compose new email.) All the activities in an App work together to create a User eXperience (UX).
- Services: A service runs in the background to perform long-running operations or to perform work for a remote processes. A service does not provide any UI, it runs only in the background with the User's input. (e.g. a service can play music in the background while the user is in a different App, or it might download data from the internet without blocking user's interaction with the Android device.)
- Content Providers: A content provider manages shared app data. There are four ways to store data in an app: it can be written to a file and stored in the file system, inserted or updated to a SQLite database, posted to the web, or saved in any other persistent storage location the App can access. Through content providers, other Apps can query or even modify the data. (e.g. Android system provides a content provider that manages the user's contact information so that any app which has permission can query the contacts.) Content providers can also be used to save the data which is private to the app for better data integrity.
- Broadcast receivers: A broadcast receiver responds to the system-wide broadcasts of announcements (e.g. a broadcast announcing that the screen has turned off, the battery is low, etc.) or from Apps (e.g. to let other apps know that some data has been downloaded to the device and is available for them to use). Broadcast receivers don't have UIs but they can show notification in the status bar to alert the user. Usually broadcast receivers are used as a gateway to other components of the app, consisting mostly of activities and services.
One unique aspect of the Android system is that any app can start another app's component (e.g. if you want to make call, send SMS, open a web page, or view a photo, there is an app which already does that and your app can make use of it, instead of developing a new activity for the same task).
When the system starts a component, it starts the process for that app (if it isn't already running, i.e. only one foreground process per app can run at any given time on an Android system) and instantiates the classes needed for that component. Thus the component runs on the process of that App that it belongs to. Therefore, unlike apps on other systems, Android apps don't have a single entry point(there is no main() method).
Because the system runs each app in a separate process, one app cannot directly activate another app's components, however the Android system can. Thus to start another app's component, one app must send a message to the system that specifies an intent to start that component, then the system will start that component.
Context
Instances of the class android.content.Context provide the connection to the Android system which executes the application. Instance of Context is required to get access to the resources of the project and the global information about the app's environment.
Let's have an easy to digest example: Consider you are in a hotel, and you want to eat something. You call roomservice and ask them to bring you things or clean up things for you. Now think of this hotel as an Android app, yourself as an activity, and the room-service person is then your context, which provides you access to the hotel resources like room-service, food items etc.
Yet an other example, You are in a restaurant sitting on a table, each table has an attendant, when ever you want to order food items you ask the attendant to do so. The attendant then places your order and your food items gets served on your table. Again in this example, the restaurant is an Android App, the tables or the customers are App components, the food items are your App resources and the attendant is your context thus giving you a way to access the resources like food items.
Activating any of the above components requires the context's instance. Not just only the above, but almost every system resource: creation of the UI using views(discussed later), creating instance of system services, starting new activities or services -- all require context.
Subscribe to:
Comments (Atom)























