[paper]; MY PERFECT IRSSI SETUP! [rebl0g]

I’ll never remember all this, so I am making a blog post if I need to set it up again later.

Installation & Getting Started

I use LMDE, so the normal debian way works. sudo apt-get install irssi screen

To learn how to use irssi including basic usage, their site goes about explaining a lot of it somewhere around here. Some basics to get started: /nick mynick /server ADD -auto -network NetworkName irc.host.com 6667 /channel ADD -auto #channel NetworkName password

Pretty easy. I switch channel windows with CTRL + left / right arrow, or CTRL + window number. Save your setup: /save

There’s a good start to a config file. (which is in ~/.irssi/).

Themes

So there really are a ton of themes, I haven’t even begun to look through them all. I just went with the standard one from the post I was reading, http://irssi.org/themefiles/xchat.theme. Hey, XChat is comforting. I saved that file into ~/.irssi/ and loaded it with: /set theme xchat Then to save the setup, I believe it is: /layout save

Scripts

This is where things get interesting. Basically, all of the cool things that XChat does for you that we all know and love… irssi does not do. By default, that is. There are a ton of scripts available to do a myriad of things, but I’ll only barely scratch the surface here. You can find a lot of scripts on Irssi’s official script site: http://scripts.irssi.org/

You can load scripts if you load the script into your ~/.irssi/scripts/ dir: /script load myscript.pl or, if you put them in your ~/.irssi/scripts/autorun/ dir like me: /run autorun/somescript.pl

Nicklist

Not having a nicklist along the side was driving me crazy. There’s a fix for that. There are a few ways to do it, actually, but I’m the most familiar with screen, and this setup is straightforward (and easy).

To start with, I saved the nicklist file from here: http://scripts.irssi.org/scripts/nicklist.pl into my ~/.irssi/scripts/autorun/ directory. Basically you start Irssi inside of a GNU Screen window, then enable the script. If you don’t run it in screen, I don’t even know what would happen, but I imagine that it wouldn’t work. screen irssi /nicklist screen

Here is a guide all about using irssi with screen, which is useful for information as well. I’ll pull some stuff from here later on: http://quadpoint.org/articles/irssi.

XChat Nick Color

This script works together with the xchat-theme (as you can find if you scroll up a bit) and does two very important things. First of all, it aligns all nicknames to the right in the chat area which creates a vertical line with the chat messages. This makes it a lot easier to read. And secondly, it will give all nicknames a unique color so it is easier to see who sends what.

Download: http://dave.waxman.org/irssi/xchatnickcolor.pl

Hilight Window

Without this, your name (or other words) don’t get highlighted so you never really know. Now, with this plugin, a new irssi window is made and all of these messages are placed in there. That’s ok, but we can also permanently set this window to display over the main chat area like this: /window new split /window name hilight /window size 4 /hilight -word yournick /help hilight Save setup again: /layout save /save

Download: http://scripts.irssi.org/scripts/hilightwin.pl More info: http://quadpoint.org/articles/irssi#hilight_window

Advanced Window List (AWL)

This one is pretty great. By default, I never knew what the irssi statusbar was saying–with this script we can change it up and make it decent. Download adv_windowlist.pl Put the script in ~/.irssi/scripts/autorun and run it: /run autorun/adv_windowlist.pl

Upon loading, AWL will create new statusbars on its own. AWL is an updated version of the older chanact.pl script. AWL has many, many new features developed by Nei. It would be worth your time to read the comments at the top of the script to get a feel for what all you can do with it (an entire article could be written on the features of this script and how to use them).

We don’t need the “Act” statusbar thing anymore. It says “(Act: 2)” when activity happens on window 2, which I just found out, but with awl and these changes we won’t need that. /statusbar window remove act There are a bunch of settings you can look into, but I am keeping it simple. /set awl

The settings I am currently using: /set awl_block -14 /set awl_display_key $Q%K|$N%n $H$C$S /set awl_display_key_active $Q%K|$N%n $H%U$C%n$S /set awl_display_nokey [$N]$H$C$S

If you like the setup, type /save to keep it. You can revert to the old act setup using /script unload adv_windowlist and /statusbar window add -after lag -priority 10 act.

Auto Away

Who doesn’t want this? It will mark you as away when Screen detects that you are not active in the session. Download: http://scripts.irssi.org/scripts/screen_away.pl

/set screen_away_active ON
/set screen_away_message
/set screen_away_nick

This one isn’t quite working right for me, though.

usercount

This shows a count of the number of users in the selected channel. Download: usercount.pl /script load usercount.pl /statusbar window add usercount # You can also add -alignment left|right option

Conclusion

As of today ( July 20th, 2013 ), that is my setup for irssi. I’m liking it quite a bit again, though I don’t know if I will stick with it… XChat is just so easy. This is nice though, and it is in a terminal, so I could install it on my VPS or any server.

Later on if I try the OTR or other features I will update this post.

Screenshot

Below is a screenshot of the (currently unbusy) #pump.io.

  • GNU Screen + the nicklist script: Along the right you see the nicks in the channel
  • hilight window script: At the top is a mention (note it specifies it was in a separate channel)
  • awl script: Along the bottom above the entry box it shows the channel windows I have open. Current channel underlined. If another channel has activity, it changes color

My Irssi Setup

 

HTC Dumlock

HTC Dumlock


HTC Dumlock is a workaround for devices with HTC’s unlock that cannot flash boot from recovery.  Put simply, we make backups of recovery and boot, then we flash the backup of recovery to boot.  When you reboot normally, you’ll be in your recovery, but since your recovery is flashed to boot, you can make changes to boot.  We’ve added some extra features to TWRP 2 to allow you to easily restore the backup of boot once you’ve booted your recovery with this method.  We also have a universal version that works with any recovery by using updater zips.

Before you install, there’s a few things you should know:


  1. First off, it puts extra wear and tear on your boot partition.  To boot recovery using this method will result in flashing your boot twice.
  2. You should keep a backup of boot handy.  If for some reason this utility ran twice before you restore your boot, then the backup of boot will be another copy of your recovery making it impossible to restore your boot.  Don’t come crying to me if you lost your boot (kernel) and didn’t make a backup first.  You only have yourself to blame.
  3. If you install a new kernel that doesn’t work and you can’t boot up, then you’ll need a computer with fastboot access to fix it.
  4. If you’re using TWRP already and have a custom theme installed, you’ll need to remove the theme until your theme gets updated with the HTC Dumlock features added to the theme.
  5. Your ROM must have root access and you must give the app root (SuperUser) permissions.

Universal Version Instructions:


  1. Download BOTH zip files and place them on your sdcard in a folder / location that you will remember.
    install-htcdumlock.zipmirror
    restore-original-boot.zipmirror
    Or download it easily on your phone using the official goo-inside.me app in /devs/teamwin/htcdumlock
  2. Reboot to your recovery.
  3. Make a backup!
  4. Install the install-htcdumlock.zip
  5. Reboot to Android.
  6. Find and open the HTC Dumlock app.
  7. If/when prompted, give the app root (SuperUser) permissions.
  8. Tap the Execute HTC Dumlock button.
  9. Wait patiently for a couple of minutes.  It takes a little while.
  10. If your device doesn’t reboot automatically, reboot it manually.  Reboot it normally.  DO NOT reboot it to recovery.
  11. You should now be in your recovery, but your recovery is flashed into boot.
  12. Before doing anything else in your recovery, install the restore-original-boot.zip
  13. Use your recovery like normal.  Flash a new kernel.  Restore a backup with a different kernel.  Do whatever you please!
  14. Consider donating!

Note, you must repeat steps 6 through 14 EVERY TIME you need to flash boot.

TWRP 2 Instructions:


  1. Install the build of TWRP using your method of choice, but you must actually flash TWRP to recovery.  No fastboot booting it.  We need it in recovery so that this build of TWRP will be flashed to your boot.  This new build of TWRP has features in it to easily restore your original boot.
  2. Reboot into recovery.
  3. Make a backup of your phone.
  4. Tap Advanced.
  5. Tap HTC Dumlock. (If you don’t see HTC Dumlock then you need to remove any custom TWRP theme that you might be using.)
  6. Tap Install HTC Dumlock.  This will install the app and binaries needed to make everything work nicely.
  7. Reboot your device.
  8. Find and open the HTC Dumlock app.
  9. If/when prompted, give the app root (SuperUser) permissions.
  10. Tap the Execute HTC Dumlock button.
  11. Wait patiently for a couple of minutes.  It takes a little while.
  12. If your device doesn’t reboot automatically, reboot it manually.  Reboot it normally.  DO NOT reboot it to recovery.
  13. You should now be in your recovery, but your recovery is flashed into boot.
  14. Tap Advanced.
  15. Tap HTC Dumlock.
  16. Tap Restore Original Boot.
  17. Use your recovery like normal.  Flash a new kernel.  Restore a backup with a different kernel.  Do whatever you please!
  18. Consider donating!

Note, you must repeat steps 8 through 18 EVERY TIME you need to flash boot.

Changelog:


2012-02-28 – v2: Add comparison of ramdisks between boot and recovery to virtually eliminate the chance that dumlock can run twice and end up replacing your backup of boot with another copy of recovery.

2012-02-21 – v1: Initial release

How does it work, the technical details:


HTC Dumlock essentially runs 3 commands to work its magic.  The commands would be similar to this:
dump_image recovery /sdcard/recovery.img
dump_image boot /sdcard/boot.img
flash_image boot /sdcard/recovery.img

Once you get back into recovery, the restore original boot looks kind of like this:
flash_image boot /sdcard/boot.img

HTC Dumlock should work with any recovery.  The only issue is that the recovery will need a method to restore your original backup of boot.  The source code is public with a GPL license.  I also realize that I probably could have done this with a shell script, but I am a much better C developer than script writer and this was the easiest way for me to do it.  You are welcome to adapt this software to a different recovery if you so choose.

DOWNLOADS:


The universal version should work with any device / recovery.  All devices with TWRP support are listed at the top of this page. Visit the device page for specific directions and downloads.

If you don’t see your device listed, then feel free to contact us about adding your device or consider using the universal version.

 

[tute]; walkthru – How to Root the HTC Sensation XL -rebl0g-

How to Root the HTC Sensation XL

When you see the HTC Sensation XL smartphone for the very first time, the one question that pops-up in the mind is whether to call this device a smartphone or a tablet. Sporting a large 4.7? inch screen, you’d be able to enjoy the touch-screen at its full and not to mention the HD videos you can enjoy on it. If you want to expand the features of your smartphone, or just want to load some root-only apps, then first you need to gain root access on your device. Here’s how you can root your HTC Sensation XL.

I. Before You Begin:

1. You must have unlocked bootloader of your device. You can unlock the bootloader from here.

2. This will void the warranty of your device. Do it at your own risk.

II. Downloading Required Files:

1. Fastboot

2. ClockworkMod Recovery Image

3. SuperSU (It’s a ZIP file attached there in the first post)

III. Installing ClockworkMod Recovery on the HTC Sensation XL:

1. Place all the files you have downloaded to your Desktop.

2. Extract files from the Fastboot archive to your Desktop. Don’t open any file.

3. Turn ON the USB debugging option on your device from Menu>>Settings>>Applications>>Development>>USB debugging.

4. Connect the device to your PC using the USB cable.

5. Transfer the SuperSU file you just downloaded to the root folder of your phone’s SD card.

6. Next, Launch a Command Prompt Window with Desktop as the current directory. To do so, press and hold the Shift key on your keyboard and right-click on any emtpy area on your Desktop, then choose Open command window here.

7. Type in the following commands into the window:

adb reboot bootloader

8. After the device has entered Fastboot mode, issue the following command:

fastboot erase cache

9. Now, enter the following command into the Command Prompt Window. Make sure to replace the recovery.img with the actual name of the Recovery Image you downloaded.

fastboot flash recovery recovery.img

10. It should flash the CWM Recovery on your device.

Well done, you now have CWM Recovery installed on your device, it’s a MoDaCo Edition Recovery and not the official one, it does work perfectly, though. Let’s see how you can root your device.

IV. Rooting the HTC Sensation XL:

1. Catching up from the Step-9 from the above section, choose the Recovery option from bootloader menu.

2. Select install zip from sdcard>>choose zip from sdcard from the Recovery menu.

3. Head to the folder where you transferred the SuperSU ZIP file and select it for flashing using the Power button.

4. Wait until it finishes flashing the file.

5. After the file has been flashed, reboot the device using reboot system now from the Recovery menu.

Brilliant! Your phone’s now rooted and a custom recovery is there on your phone. If you’ve been waiting to flash a custom ROM on your device, this is the perfect time to do it.

V. Flash a Custom ROM (Optional):

1. If you are ready to flash custom ROMs on your device, head to the How To Flash a Custom ROM on the HTC Sensation XL to learn how to do that.

If you need help with this procedure, please ask in the comments below or in the forum.

This is part of our Android How To’s. We have how to’s on rooting, loading ROMs, and tons of other tips and tricks for your specific device or for Android devices in general! For all of our Android How To’s, head here.

[info]; TWRP compilation (rebl0g thx xda/TeamWIN)

All of TWRP 2.x source is public. You can compile it on your own. This guide isn’t going to be a step-by-step, word-for-word type of guide. If you’re not familiar with basic Linux commands and/or building in AOSP then you probably won’t be able to do this.

You can currently use Omni 4.3, Omni 4.4, Omni 5.0, CM10.0, CM10.1, CM10.2, and CM11.0 source code. Omni 4.4 or 5.0 is recommended. (If for some reason you need to compile in an older tree like CM9 or CM7, you will have to use the android-4.4 branch which we will not continue to update.)

If you are using CM, you’ll need to replace CM/bootable/recovery with this:
https://github.com/omnirom/android_bootable_recovery
Select the newest branch available. This step is not necessary with Omni because Omni already includes TWRP source by default.

*BEFORE YOU COMPILE*
Note: If you add or change any flags, you will need to make clean or make clobber before recompiling or your flag changes will not be picked up.

Now that you have the source code, you’ll need to set or change a few build flags for your device(s). Find the BoardConfig.mk for your device. The BoardConfig.mk is in your devices/manufacturer/codename folder (e.g. devices/lge/hammerhead/BoardConfig.mk). First, scan the BoardConfig.mk file for
TARGET_RECOVERY_INITRC :=
If your device has this line, it will have a path to a custom, prebuilt init.rc that is used in recovery. Most likely you will need to change the custom init.rc slightly. Find the recovery’s init.rc file and open it. Near the top you will see something like this:

Code:
on init
	export PATH /sbin
	export LD_LIBRARY_PATH .:/sbin

Add the last line needed. This line is needed to get the linker running. Unlike ClockworkMod, TWRP is a dynamically linked recovery. Dynamic linking allows us to save a considerable amount of space to help make sure that TWRP recovery images will fit on more devices. It also lets us use dynamically linked touchscreen binaries as seen on the Motorola Photon and Atrix and the HP TouchPad without having to mount /system.

Your board config also needs to include architecture and platform settings. Usually these are already included if you’re using device configs that someone else created, but if you created your own, you may need to add them. Without them, recovery may seg fault during startup and you’ll just see the teamwin curtain flash on the screen over and over.

We usually put all of our flags at the bottom of the BoardConfig.mk under a heading of #twrp For all devices you’ll need to set a resolution. TWRP needs to know the resolution at compile time so that it knows what stock theme to include. You can only use resolutions that have a theme so if you don’t see your resolution, you’ll have to pick one that’s less than or equal to your resolution. You can find the list of stock themes in bootable/recovery/gui/devices. So if your device has a 540×960 display, you would add this:
DEVICE_RESOLUTION := 540×960

Note that themes do not rotate, so the 1280×800 theme is intended for tablets and would not work on the Samsung Galaxy Note 1 that expects a 800×1280 type of theme.

In addition to the resolution, we have the following build flags:
RECOVERY_SDCARD_ON_DATA := true — this enables proper handling of /data/media on devices that have this folder for storage (most Honeycomb and devices that originally shipped with ICS like Galaxy Nexus)
RECOVERY_GRAPHICS_USE_LINELENGTH := true — fixes slanty looking graphics on some devices
BOARD_HAS_NO_REAL_SDCARD := true — disables things like sdcard partitioning and may save you some space if TWRP isn’t fitting in your recovery patition
TW_INCLUDE_DUMLOCK := true — includes HTC Dumlock for devices that need it
TW_NO_BATT_PERCENT := true — disables the display of the battery percentage for devices that don’t support it properly
TW_CUSTOM_POWER_BUTTON := 107 — custom maps the power button for the lockscreen
TW_NO_REBOOT_BOOTLOADER := true — removes the reboot bootloader button from the reboot menu
TW_NO_REBOOT_RECOVERY := true — removes the reboot recovery button from the reboot menu
TW_NO_USB_STORAGE := true — removes the USB storage button on devices that don’t support USB storage
RECOVERY_TOUCHSCREEN_SWAP_XY := true — swaps the mapping of touches between the X and Y axis
RECOVERY_TOUCHSCREEN_FLIP_Y := true — flips y axis touchscreen values
RECOVERY_TOUCHSCREEN_FLIP_X := true — flips x axis touchscreen values
TW_ALWAYS_RMRF := true — forces the rm -rf option to always be on (needed for some Motorola devices)
TW_NEVER_UNMOUNT_SYSTEM := true — never unmount system (needed for some Motorola devices)
TW_INCLUDE_INJECTTWRP := true — adds ability to inject TWRP into some Samsung boot images for Samsung devices that have recovery as a second ramdisk in the boot image
TW_DEFAULT_EXTERNAL_STORAGE := true — defaults to external storage instead of internal on dual storage devices (largely deprecated)
TWRP_EVENT_LOGGING := true — enables touch event logging to help debug touchscreen issues (don’t leave this on for a release – it will fill up your logfile very quickly)

Here’s some flags that may help you, but are not specific to TWRP (works in CWM too):
This flag has multiple options, but can be used to set different graphics modes that may be need to correct color space issues on some devices:
TARGET_RECOVERY_PIXEL_FORMAT := “BGRA_8888″
TARGET_RECOVERY_PIXEL_FORMAT := “RGBX_8888″
TARGET_RECOVERY_PIXEL_FORMAT := “RGB_565″

BOARD_HAS_FLIPPED_SCREEN := true — flips the screen upside down for screens that were mounted upside-down
TARGET_PREBUILT_RECOVERY_KERNEL := path/to/kernel — use to specify a kernel specifically for building recovery

*RECOVERY.FSTAB*
TWRP 2.5 and higher supports some new recovery.fstab features that you can use to extend TWRP’s backup/restore capabilities. You do not have to add fstab flags as most partitions are handled automatically.

Note that TWRP does not currently support the “fstab 2″ version of fstab files seen in 4.3 or higher. You will still need to use the “old” format of fstab for TWRP (example of that format is below). To maximize TWRP’s compatibility with your build tree, you can create a twrp.fstab and use PRODUCT_COPY_FILES to place the file in /etc/twrp.fstab When TWRP boots, if it finds a twrp.fstab in the ramdisk it will rename /etc/recovery.fstab to /etc/recovery.fstab.bak and then rename /etc/twrp.fstab to /etc/recovery.fstab. Effectively this will “replace” the fstab 2 file that your device files are providing with the TWRP fstab allowing you to maintain compatibility within your device files and with other recoveries.

Code:
PRODUCT_COPY_FILES += device/lge/hammerhead/twrp.fstab:recovery/root/etc/twrp.fstab

The fstab in TWRP can contain some “flags” for each partition listed in the fstab.

Here’s a sample TWRP fstab for the Galaxy S4 that we will use for reference:

Code:
/boot       emmc        /dev/block/platform/msm_sdcc.1/by-name/boot
/system     ext4        /dev/block/platform/msm_sdcc.1/by-name/system
/data       ext4        /dev/block/platform/msm_sdcc.1/by-name/userdata length=-16384
/cache      ext4        /dev/block/platform/msm_sdcc.1/by-name/cache
/recovery   emmc        /dev/block/platform/msm_sdcc.1/by-name/recovery
/efs        ext4        /dev/block/platform/msm_sdcc.1/by-name/efs                            flags=display="EFS";backup=1
/external_sd     vfat       /dev/block/mmcblk1p1    /dev/block/mmcblk1   flags=display="Micro SDcard";storage;wipeingui;removable
/usb-otg         vfat       /dev/block/sda1         /dev/block/sda       flags=display="USB-OTG";storage;wipeingui;removable
/preload    ext4        /dev/block/platform/msm_sdcc.1/by-name/hidden                            flags=display="Preload";wipeingui;backup=1
/modem      ext4        /dev/block/platform/msm_sdcc.1/by-name/apnhlos
/mdm		emmc		/dev/block/platform/msm_sdcc.1/by-name/mdm

Flags are added to the end of the partition listing in the fstab separated by white space (spaces or tabs are fine). The flags affect only that partition but not any of the others. Flags are separated by semicolons. If your display name is going to have a space, you must surround the display name with quotes.

Code:
/external_sd  vfat  /dev/block/mmcblk1p1  flags=display="Micro SDcard";storage;wipeingui;removable

The flags for this partition give it a display name of “Micro SDcard” which is displayed to the user. wipeingui makes this partition available for wiping in the advanced wipe menu. The removable flag indicates that sometimes this partition may not be present preventing mounting errors from being displayed during startup. Here is a full list of flags:
removable — indicates that the partition may not be present preventing mounting errors from being displayed during boot
storage — indicates that the partition can be used as storage which makes the partition available as storage for backup, restore, zip installs, etc.
settingsstorage — only one partition should be set as settings storage, this partition is used as the location for storing TWRP’s settings file
canbewiped — indicates that the partition can be wiped by the back-end system, but may not be listed in the GUI for wiping by the user
userrmrf — overrides the normal format type of wiping and only allows the partition to be wiped using the rm -rf command
backup= — must be succeeded by the equals sign, so backup=1 or backup=0, 1 indicates that the partition can be listed in the backup/restore list while 0 ensures that this partition will not show up in the backup list.
wipeingui — makes the partition show up in the GUI to allow the user to select it for wiping in the advanced wipe menu
wipeduringfactoryreset — the partition will be wiped during a factory reset
ignoreblkid — blkid is used to determine what file system is in use by TWRP, this flag will cause TWRP to skip/ignore the results of blkid and use the file system specified in the fstab only
retainlayoutversion — causes TWRP to retain the .layoutversion file in /data on devices like Sony Xperia S which sort of uses /data/media but still has a separate /sdcard partition
symlink= — causes TWRP to run an additional mount command when mounting the partition, generally used with /data/media to create /sdcard
display= — sets a display name for the partition for listing in the GUI
storagename= — sets a storage name for the partition for listing in the GUI storage list
backupname= — sets a backup name for the partition for listing in the GUI backup/restore list
length= — usually used to reserve empty space at the end of the /data partition for storing the decryption key when Android’s full device encryption is present, not setting this may lead to the inability to encrypt the device
canencryptbackup= — 1 or 0 to enable/disable, makes TWRP encrypt the backup of this partition if the user chooses encryption (only applies to tar backups, not images)
userdataencryptbackup= — 1 or 0 to enable/disable, makes TWRP encrypt only the userdata portion of this partition, certain subfuldes like /data/app would not be encrypted to save time
subpartitionof= — must be succeeded by the equals sign and the path of the partition it is a subpartition of. A subpartition is treated as “part” of the main partition so for instance, TWRP automatically makes /datadata a subpartition of /data. This means that /datadata will not show up in the GUI listings, but /datadata would be wiped, backed up, restored, mounted, and unmounted anytime those operations are performed on /data. A good example of the use of subpartitions is the 3x efs partitions on the LG Optimus G:

Code:
/efs1         emmc   /dev/block/mmcblk0p12 flags=backup=1;display=EFS
/efs2         emmc   /dev/block/mmcblk0p13 flags=backup=1;subpartitionof=/efs1
/efs3         emmc   /dev/block/mmcblk0p14 flags=backup=1;subpartitionof=/efs1

This lumps all 3 partitions into a single “EFS” entry in the TWRP GUI allowing all three to be backed up and restored together under a single entry.

If you have questions, feel free to stop by #twrp on Freenode. If you post here I may not see it for a while as I have lots of threads out there and there’s no way for me to keep track of them all. If you successfully port TWRP to a new device, please let us know! We love to hear success stories!

If you have code changes that you’d like to submit, please submit them through the Omni Gerrit server. Guide is here.

Once you get Omni or CM sync’ed and your TWRP flags set, you should do a source ./build/envsetup.sh We usually lunch for the device in question, so something like “lunch omni_hammerhead-eng”.

After you lunch successfully for your device this is the command used for most devices:

Code:
make clean && make -j# recoveryimage

Replace the # with the core count +1, so if you have a dual core it’s -j3 and a quad core becomes -j5, etc. If you’re dealing with a “typical” Samsung device, then you’ll need to

Code:
make -j# bootimage

Most Samsung devices have the recovery included as an extra ramdisk in the boot image instead of a separate recovery partition as found on most other devices.

Notes about 4.4 Kit Kat ROMs and SELinux
There’s absolutely no SELinux support in ICS trees or older. libselinux is not included in these trees and some dependencies for libselinux don’t exist elsewhere in these older trees so there’s no way to get SELinux support unless you move to a newer tree. I recommend using a 4.3 based tree or higher.

SELinux support is included in all builds of TWRP so long as you build in a tree that has libselinux present. However, for SELinux support to work, your kernel must support EXT4 security labels as well. If you’re using an older kernel, your TWRP won’t support SELinux and you will get errors when installing 4.4 Kit Kat ROMs due to set_metadata not being able to set SELinux contexts. You’ll see an error in the recovery log stating something along the lines of “Operation not supported on transport endpoint.” This means you need to add proper support to the kernel you are using in recovery. (Yes, at least in most cases, recovery has its own kernel.)

In the kernel source I was testing, the needed flag was CONFIG_EXT4_FS_SECURITY=y and the option was called Ext4 Security Labels under the file systems menu. If you want full SELinux in your kernel you will need to add auditing support (usually found under general setup) then enable SELinux under security options. There’s multiple flags and some dependencies involved so your setup may vary slightly.

The android-4.4 branch of TWRP from Omni now includes a check during boot. You will see text in the log and in the console indicating the SELinux status. This should help you identify what issue(s) you may have with SELinux support.

Deprecated build flags:
For TWRP < 2.5:
The below is how you can add custom / special partitions to the list of partitions available for backup. The SP1_NAME must match the name of a partition defined in recovery.fstab. The SP1_DISPLAY_NAME is the name displayed on the backup page if it needs to be different than SP1_NAME. SP1_BACKUP_METHOD defines how the partition should be backed up (files or image). And SP1_MOUNTABLE determines if the partition can be mounted.
SP1_NAME := “pds”
SP1_BACKUP_METHOD := files
SP1_MOUNTABLE := 1
SP2_NAME := “osh”
SP2_DISPLAY_NAME := “Webtop”
SP2_BACKUP_METHOD := files
SP2_MOUNTABLE := 1
SP3_NAME := “preinstall”
SP3_BACKUP_METHOD := image
SP3_MOUNTABLE := 0

Last edited by Dees_Troy; 2nd January 2015 at 04:42 PM.
The Following 179 Users Say Thank You to Dees_Troy For This Useful Post: [ View ]

18th October 2012, 05:30 PM   |  #2

Dees_Troy's Avatar
OP Senior Recognized Developer
Flag KC MO
Thanks Meter: 10,213

 
1,630 posts
Join Date: Mar 2008

Donate to Me

More

So, now, hopefully you’ve compiled TWRP for your device and gotten it working. Now, you’d like to know how to get TWRP officially supported for your device so that it can be installed automatically with GooManager. In order for us to add “official support” for your device we’ll need the following:
1) Device configuration files to compile TWRP from source for your device. This means that you cannot have repacked a recovery.img by hand to get it working. We need to be able to compile it from source so that we can easily release future updates.
2) A copy of a build prop for your device (it’s in /system/build.prop) so that we can add the correct device information to GooManager
3) We’ll build a copy of TWRP and send it to you for validation. Once you’ve validated that we can build a working image for your device, we’ll add it to GooManager.

Note that we won’t take credit for your port. You’ll still get to post it on XDA to collect all the credit that goes with releasing something new for your device. Also note that it’s not always possible to provide automated installs for all devices.

Last edited by Dees_Troy; 7th November 2012 at 05:41 PM.

[tute]; How to Copy Files to HTC One Using TWRP Mount and ADB

One of the pitfalls of HTC One not having an extra microSD card slot is that if you make the mistake of formatting your whole internal storage or perhaps just did something wrong with no system on it, you will end up with a beautiful, shiny brick.

This also works on ANY Android device such as Galaxy Note 3, Note 2, Galaxy S4, Galaxy S3, Galaxy S2, HTC One X, and any Android device with TWRP recovery.

Well, this is pretty easy to solve if you have a OTG USB cable and USB flash drive as TWRP let’s you install files using OTG USB cable and USB flash drive.  But for some of you this may not be an option or you may have to wait couple days to order the OTG cable from Amazon.

There is a way to “push”(or copy) files to your phone using the TWRP mount function and adb.

Ok, here’s how to do it:

Boot TWRP, then select “Mount”, then select only “Data” and connect your HTC One to your computer.

Then download fastboot.zip and unzip, you probably will find a new directory called fastboot under your Downloads directory.

Copy the ROM you want to install to the fastboot folder.

Open a command prompt then type:

cd Downloads\fastboot
adb push ROM.zip /sdcard/.

Replace ROM.zip with the ROM filename you copied earlier to fastboot folder.

This will copy your ROM to the internal storage so once it’s done, just use TWRP to install ROM.

[0day exploit]; memleak 15′ by xires for d4rkstorm // android community

// for teamWIN // d4rkstorm sign // 2015

#define __KERNEL__
#define CONFIG_LBD
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <linux/mempool.h>

struct crypt_config {
struct dm_dev *dev;
sector_t start;

mempool_t *io_pool;
mempool_t *page_pool;

/* crypto related data */
struct crypt_iv_operations *iv_gen_ops;
char *iv_mode;
void *iv_gen_private;
sector_t iv_offset;
unsigned int iv_size;
struct crypto_tfm *tfm;
unsigned int key_size;
u8 key[0];
} __attribute__ ((packed));

int keysearch(char *mem, int size) {
int i,j;
struct crypt_config *cr;
for(i = 0; i < (size – sizeof(struct crypt_config)); i++,mem++) {
cr = (struct crypt_config *) mem;
if(
(void *) cr->io_pool > (void *) 0xc0000000 &&
(void *) cr->tfm > (void *) 0xc0000000 &&
(void *) cr->dev > (void *) 0xc0000000 &&
(void *) cr->io_pool > (void *) 0xc0000000 &&
(void *) cr->page_pool > (void *) 0xc0000000 &&
(void *) cr->iv_gen_ops > (void *) 0xc0000000 &&
(void *) cr->iv_mode > (void *) 0xc0000000 &&
(void *) cr->iv_gen_private > (void *) 0xc0000000 &&
(cr->key_size == 32 || cr->key_size == 64) &&
(cr->iv_size == 32 || cr->iv_size == 64) &&
cr->iv_offset == 0
) {
if(cr->start > 0)
printf(“offset: %ld blocks\n”,(unsigned long int ) cr->start);
printf(“keylenght: %d\n”,(cr->key_size * 8));
printf(“key: “);
for(j = 0; j < cr->key_size; j++)
printf(“%02X”,cr->key[j]);
printf(“\n”);
}
}
return(0);
}

int main(int argc, char **argv) {
int fd;
char *mem = NULL;
struct stat st;
if(argc < 2)
{
printf(“Usage: %s [memory dump file]\n”,argv[0]);
exit(-1);
}
if(stat(argv[1],&st) == -1)
{
perror(“stat()”);
printf(“Failed to stat %s\n”,argv[1]);
exit(-1);
}
fd = open(argv[1],O_RDONLY);
if(fd == -1)
{
perror(“open()”);
printf(“Failed to open %s\n”,argv[1]);
exit(-1);
}
mem = mmap(0,(int)st.st_size, PROT_READ, MAP_SHARED, fd, 0);
if(mem == ((void *) -1))
{
perror(“mmap()”);
exit(-1);
}
(void)keysearch(mem,(int)st.st_size);
return(0);
}

[tute]; Building Your First App on Android [rebl0g]

Building Your First App

Dependencies

Welcome to Android application development!

This class teaches you how to build your first Android app. You’ll learn how to create an Android project and run a debuggable version of the app. You’ll also learn some fundamentals of Android app design, including how to build a simple user interface and handle user input.

Set Up Your Environment


Before you start this class, be sure you have your development environment set up. You need to:

  1. Download Android Studio.
  2. Download the latest SDK tools and platforms using the SDK Manager.

Note: Although most of this training class expects that you’re using Android Studio, some procedures include alternative instructions for using the SDK tools from the command line instead.

This class uses a tutorial format to create a small Android app that teaches you some fundamental concepts about Android development, so it’s important that you follow each step.

Creating an Android Project

An Android project contains all the files that comprise the source code for your Android app.

This lesson shows how to create a new project either using Android Studio or using the SDK tools from a command line.

Note: You should already have the Android SDK installed, and if you’re using Android Studio, you should also have Android Studio installed. If you don’t have these, follow the guide to Installing the Android SDK before you start this lesson.

Create a Project with Android Studio


    1. In Android Studio, create a new project:
      • If you don’t have a project opened, in the Welcome screen, click New Project.
      • If you have a project opened, from the File menu, select New Project.

Figure 1. Configuring a new project in Android Studio.

    1. Under Configure your new project, fill in the fields as shown in figure 1 and click Next.It will probably be easier to follow these lessons if you use the same values as shown.
      • Application Name is the app name that appears to users. For this project, use “My First App.”
      • Company domain provides a qualifier that will be appended to the package name; Android Studio will remember this qualifier for each new project you create.
      • Package name is the fully qualified name for the project (following the same rules as those for naming packages in the Java programming language). Your package name must be unique across all packages installed on the Android system. You can Edit this value independently from the application name or the company domain.
      • Project location is the directory on your system that holds the project files.
    2. Under Select the form factors your app will run on, check the box for Phone and Tablet.
    3. For Minimum SDK, select API 8: Android 2.2 (Froyo).The Minimum Required SDK is the earliest version of Android that your app supports, indicated using the API level. To support as many devices as possible, you should set this to the lowest version available that allows your app to provide its core feature set. If any feature of your app is possible only on newer versions of Android and it’s not critical to the app’s core feature set, you can enable the feature only when running on the versions that support it (as discussed in Supporting Different Platform Versions).
    4. Leave all of the other options (TV, Wear, and Glass) unchecked and click Next.
  1. Under Add an activity to your project, select Blank Activity and click Next.
  2. Under Describe the new activity for your project, leave the fields as they are and click Finish.

Your Android project is now a basic “Hello World” app that contains some default files. Take a moment to review the most important of these:

app/src/main/res/layout/activity_my.xml
This is the XML layout file for the activity you added when you created the project with Android Studio. Following the New Project workflow, Android Studio presents this file with both a text view and a preview of the screen UI. The file includes some default settings and a TextView element that displays the message, “Hello world!”
app/src/main/java/com.mycompany.myfirstapp/MyActivity.java
A tab for this file appears in Android Studio when the New Project workflow finishes. When you select the file you see the class definition for the activity you created. When you build and run the app, the Activity class starts the activity and loads the layout file that says “Hello World!”
app/src/res/AndroidManifest.xml
The manifest file describes the fundamental characteristics of the app and defines each of its components. You’ll revisit this file as you follow these lessons and add more components to your app.
app/build.gradle
Android Studio uses Gradle to compile and build your app. There is a build.gradle file for each module of your project, as well as a build.gradle file for the entire project. Usually, you’re only interested in the build.gradle file for the module, in this case the app or application module. This is where your app’s build dependencies are set, including the defaultConfig settings:

  • compiledSdkVersion is the platform version against which you will compile your app. By default, this is set to the latest version of Android available in your SDK. (It should be Android 4.1 or greater; if you don’t have such a version available, you must install one using the SDK Manager.) You can still build your app to support older versions, but setting this to the latest version allows you to enable new features and optimize your app for a great user experience on the latest devices.
  • applicationId is the fully qualified package name for your application that you specified during the New Project workflow.
  • minSdkVersion is the Minimum SDK version you specified during the New Project workflow. This is the earliest version of the Android SDK that your app supports.
  • targetSdkVersion indicates the highest version of Android with which you have tested your application. As new versions of Android become available, you should test your app on the new version and update this value to match the latest API level and thereby take advantage of new platform features. For more information, read Supporting Different Platform Versions.

See Building Your Project with Gradle for more information about Gradle.

Note also the /res subdirectories that contain the resources for your application:

drawable-hdpi/
Directory for drawable objects (such as bitmaps) that are designed for high-density (hdpi) screens. Other drawable directories contain assets designed for other screen densities. Here you’ll find the ic_launcher.png that appears when you run the default app.
layout/
Directory for files that define your app’s user interface like activity_my.xml, discussed above, which describes a basic layout for the MyActivity class.
values/
Directory for other XML files that contain a collection of resources, such as string and color definitions. The strings.xml file defines the “Hello world!” string that displays when you run the default app.

To run the app, continue to the next lesson.

Create a Project with Command Line Tools


If you’re not using the Android Studio IDE, you can instead create your project using the SDK tools from a command line:

  1. Change directories into the Android SDK’s tools/ path.
  2. Execute:
    android list targets

    This prints a list of the available Android platforms that you’ve downloaded for your SDK. Find the platform against which you want to compile your app. Make a note of the target ID. We recommend that you select the highest version possible. You can still build your app to support older versions, but setting the build target to the latest version allows you to optimize your app for the latest devices.

    If you don’t see any targets listed, you need to install some using the Android SDK Manager tool. See Adding SDK Packages.

  3. Execute:
    android create project --target <target-id> --name MyFirstApp \
    --path <path-to-workspace>/MyFirstApp --activity MyActivity \
    --package com.example.myfirstapp
    

    Replace <target-id> with an ID from the list of targets (from the previous step) and replace <path-to-workspace> with the location in which you want to save your Android projects.

Tip: Add the platform-tools/ as well as the tools/ directory to your PATH environment variable.

Your Android project is now a basic “Hello World” app that contains some default files. To run the app, continue to the next lesson.

Running Your App

If you followed the previous lesson to create an Android project, it includes a default set of “Hello World” source files that allow you to immediately run the app.

How you run your app depends on two things: whether you have a real device running Android and whether you’re using Android Studio. This lesson shows you how to install and run your app on a real device and on the Android emulator, and in both cases with either Android Studio or the command line tools.

Run on a Real Device


If you have a device running Android, here’s how to install and run your app.

Set up your device

  1. Plug in your device to your development machine with a USB cable. If you’re developing on Windows, you might need to install the appropriate USB driver for your device. For help installing drivers, see the OEM USB Drivers document.
  2. Enable USB debugging on your device.
    • On most devices running Android 3.2 or older, you can find the option under Settings > Applications > Development.
    • On Android 4.0 and newer, it’s in Settings > Developer options.

      Note: On Android 4.2 and newer, Developer options is hidden by default. To make it available, go to Settings > About phone and tap Build number seven times. Return to the previous screen to find Developer options.

Run the app from Android Studio

  1. Select one of your project’s files and click Run from the toolbar.
  2. In the Choose Device window that appears, select the Choose a running device radio button, select your device, and click OK .

Android Studio installs the app on your connected device and starts it.

Run the app from a command line

  1. Change directories to the root of your Android project and execute:
    ant debug
  2. Make sure the Android SDK platform-tools/ directory is included in your PATH environment variable, then execute:
    adb install bin/MyFirstApp-debug.apk
  3. On your device, locate MyFirstApp and open it.

That’s how you build and run your Android app on a device! To start developing, continue to the next lesson.

Run on the Emulator


Whether you’re using Android Studio or the command line, to run your app on the emulator you need to first create an Android Virtual Device (AVD). An AVD is a device configuration for the Android emulator that allows you to model a specific device.

Create an AVD

  1. Launch the Android Virtual Device Manager:
    • In Android Studio, select Tools > Android > AVD Manager, or click the AVD Manager icon in the toolbar.
    • Or, from the command line, change directories to <sdk>/tools/ and execute:
      android avd

      Note: The AVD Manager that appears when launched from the command line is different from the version in Android Studio, so the following instructions may not apply.

    Figure 1. The AVD Manager main screen shows your current virtual devices.

  2. On the AVD Manager main screen (figure 1), click Create Virtual Device.
  3. In the Select Hardware window, select a device configuration, such as Nexus 6, then click Next.
  4. Select the desired system version for the AVD and click Next.
  5. Verify the configuration settings, then click Finish.

For more information about using AVDs, see Managing AVDs with AVD Manager.

Run the app from Android Studio

  1. In Android Studio, select your project and click Run from the toolbar.
  2. In the Choose Device window, click the Launch emulator radio button.
  3. From the Android virtual device pull-down menu, select the emulator you created, and click OK.

It can take a few minutes for the emulator to load itself. You may have to unlock the screen. When you do, My First App appears on the emulator screen.

Run your app from the command line

  1. Change directories to the root of your Android project and execute:
    ant debug
  2. Make sure the Android SDK platform-tools/ directory is included in your PATH environment variable, then execute:
    adb install bin/MyFirstApp-debug.apk
  3. On the emulator, locate MyFirstApp and open it.

That’s how you build and run your Android app on the emulator!

Building a Simple User Interface

In this lesson, you create a layout in XML that includes a text field and a button. In the next lesson, your app responds when the button is pressed by sending the content of the text field to another activity.

The graphical user interface for an Android app is built using a hierarchy of View and ViewGroup objects. View objects are usually UI widgets such as buttons or text fields. ViewGroup objects are invisible view containers that define how the child views are laid out, such as in a grid or a vertical list.

Android provides an XML vocabulary that corresponds to the subclasses of View and ViewGroup so you can define your UI in XML using a hierarchy of UI elements.

Layouts are subclasses of the ViewGroup. In this exercise, you’ll work with a LinearLayout.

Figure 1. Illustration of how ViewGroup objects form branches in the layout and contain other View objects.

Create a Linear Layout


  1. In Android Studio, from the res/layout directory, open the activity_my.xml file.The BlankActivity template you chose when you created this project includes the activity_my.xml file with a RelativeLayout root view and a TextView child view.
  2. In the Preview pane, click the Hide icon to close the Preview pane.In Android Studio, when you open a layout file, you’re first shown the Preview pane. Clicking elements in this pane opens the WYSIWYG tools in the Design pane. For this lesson, you’re going to work directly with the XML.
  3. Delete the <TextView> element.
  4. Change the <RelativeLayout> element to <LinearLayout>.
  5. Add the android:orientation attribute and set it to "horizontal".
  6. Remove the android:padding attributes and the tools:context attribute.

The result looks like this:

res/layout/activity_my.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >
</LinearLayout>

LinearLayout is a view group (a subclass of ViewGroup) that lays out child views in either a vertical or horizontal orientation, as specified by the android:orientation attribute. Each child of a LinearLayout appears on the screen in the order in which it appears in the XML.

Two other attributes, android:layout_width and android:layout_height, are required for all views in order to specify their size.

Because the LinearLayout is the root view in the layout, it should fill the entire screen area that’s available to the app by setting the width and height to "match_parent". This value declares that the view should expand its width or height to match the width or height of the parent view.

For more information about layout properties, see the Layout guide.

Add a Text Field


As with every View object, you must define certain XML attributes to specify the EditText object’s properties.

  1. In the activity_my.xml file, within the <LinearLayout> element, define an <EditText> element with the id attribute set to @+id/edit_message.
  2. Define the layout_width and layout_height attributes as wrap_content.
  3. Define a hint attribute as a string object named edit_message.

The <EditText> element should read as follows:

res/layout/activity_my.xml

<EditText android:id="@+id/edit_message"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:hint="@string/edit_message" />

Here are the <EditText> attributes you added:

android:id
This provides a unique identifier for the view, which you can use to reference the object from your app code, such as to read and manipulate the object (you’ll see this in the next lesson).The at sign (@) is required when you’re referring to any resource object from XML. It is followed by the resource type (id in this case), a slash, then the resource name (edit_message).

The plus sign (+) before the resource type is needed only when you’re defining a resource ID for the first time. When you compile the app, the SDK tools use the ID name to create a new resource ID in your project’s gen/R.java file that refers to the EditText element. With the resource ID declared once this way, other references to the ID do not need the plus sign. Using the plus sign is necessary only when specifying a new resource ID and not needed for concrete resources such as strings or layouts. See the sidebox for more information about resource objects.

android:layout_width and android:layout_height
Instead of using specific sizes for the width and height, the "wrap_content" value specifies that the view should be only as big as needed to fit the contents of the view. If you were to instead use "match_parent", then the EditText element would fill the screen, because it would match the size of the parent LinearLayout. For more information, see the Layouts guide.
android:hint
This is a default string to display when the text field is empty. Instead of using a hard-coded string as the value, the "@string/edit_message" value refers to a string resource defined in a separate file. Because this refers to a concrete resource (not just an identifier), it does not need the plus sign. However, because you haven’t defined the string resource yet, you’ll see a compiler error at first. You’ll fix this in the next section by defining the string.

Note: This string resource has the same name as the element ID: edit_message. However, references to resources are always scoped by the resource type (such as id or string), so using the same name does not cause collisions.

Add String Resources


By default, your Android project includes a string resource file at res/values/strings.xml. Here, you’ll add a new string named "edit_message" and set the value to “Enter a message.”

  1. In Android Studio, from the res/values directory, open strings.xml.
  2. Add a line for a string named "edit_message" with the value, “Enter a message”.
  3. Add a line for a string named "button_send" with the value, “Send”.You’ll create the button that uses this string in the next section.
  4. Remove the line for the "hello world" string.

The result for strings.xml looks like this:

res/values/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">My First App</string>
    <string name="edit_message">Enter a message</string>
    <string name="button_send">Send</string>
    <string name="action_settings">Settings</string>
    <string name="title_activity_main">MainActivity</string>
</resources>

For text in the user interface, always specify each string as a resource. String resources allow you to manage all UI text in a single location, which makes the text easier to find and update. Externalizing the strings also allows you to localize your app to different languages by providing alternative definitions for each string resource.

For more information about using string resources to localize your app for other languages, see the Supporting Different Devices class.

Add a Button


  1. In Android Studio, from the res/layout directory, edit the activity_my.xml file.
  2. Within the <LinearLayout> element, define a <Button> element immediately following the <EditText> element.
  3. Set the button’s width and height attributes to "wrap_content" so the button is only as big as necessary to fit the button’s text label.
  4. Define the button’s text label with the android:text attribute; set its value to the button_send string resource you defined in the previous section.

Your <LinearLayout> should look like this:

res/layout/activity_my.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >
      <EditText android:id="@+id/edit_message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="@string/edit_message" />
      <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button_send" />
</LinearLayout>

Note: This button doesn’t need the android:id attribute, because it won’t be referenced from the activity code.

The layout is currently designed so that both the EditText and Button widgets are only as big as necessary to fit their content, as shown in figure 2.

Figure 2. The EditText and Button widgets have their widths set to "wrap_content".

This works fine for the button, but not as well for the text field, because the user might type something longer. It would be nice to fill the unused screen width with the text field. You can do this inside a LinearLayout with the weight property, which you can specify using the android:layout_weight attribute.

The weight value is a number that specifies the amount of remaining space each view should consume, relative to the amount consumed by sibling views. This works kind of like the amount of ingredients in a drink recipe: “2 parts soda, 1 part syrup” means two-thirds of the drink is soda. For example, if you give one view a weight of 2 and another one a weight of 1, the sum is 3, so the first view fills 2/3 of the remaining space and the second view fills the rest. If you add a third view and give it a weight of 1, then the first view (with weight of 2) now gets 1/2 the remaining space, while the remaining two each get 1/4.

The default weight for all views is 0, so if you specify any weight value greater than 0 to only one view, then that view fills whatever space remains after all views are given the space they require.

Make the Input Box Fill in the Screen Width


To fill the remaining space in your layout with the EditText element, do the following:

  1. In the activity_my.xml file, assign the <EditText> element’s layout_weight attribute a value of 1.
  2. Also, assign <EditText> element’s layout_width attribute a value of 0dp.

    res/layout/activity_my.xml

    <EditText
        android:layout_weight="1"
        android:layout_width="0dp"
        ... />

    To improve the layout efficiency when you specify the weight, you should change the width of the EditText to be zero (0dp). Setting the width to zero improves layout performance because using "wrap_content" as the width requires the system to calculate a width that is ultimately irrelevant because the weight value requires another width calculation to fill the remaining space.

    Figure 3 shows the result when you assign all weight to the EditText element.

    Figure 3. The EditText widget is given all the layout weight, so it fills the remaining space in the LinearLayout.

Here’s how your complete activity_my.xmllayout file should now look:

res/layout/activity_my.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">
    <EditText android:id="@+id/edit_message"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="@string/edit_message" />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button_send" />
</LinearLayout>

Run Your App


This layout is applied by the default Activity class that the SDK tools generated when you created the project. Run the app to see the results:

  • In Android Studio, from the toolbar, click Run .
  • Or from a command line, change directories to the root of your Android project and execute:
    ant debug
    adb install bin/MyFirstApp-debug.apk

Continue to the next lesson to learn how to respond to button presses, read content from the text field, start another activity, and more.

Starting Another Activity

After completing the previous lesson, you have an app that shows an activity (a single screen) with a text field and a button. In this lesson, you’ll add some code to MyActivity that starts a new activity when the user clicks the Send button.

Respond to the Send Button


  1. In Android Studio, from the res/layout directory, edit the activity_my.xml file.
  2. To the <Button> element, add the android:onClick attribute.

    res/layout/activity_my.xml

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button_send"
        android:onClick="sendMessage" />

    The android:onClick attribute’s value, "sendMessage", is the name of a method in your activity that the system calls when the user clicks the button.

  3. In the java/com.mycompany.myfirstapp directory, open the MyActivity.java file.
  4. Within the MyActivity class, add the sendMessage() method stub shown below.

    java/com.mycompany.myfirstapp/MyActivity.java

    /** Called when the user clicks the Send button */
    public void sendMessage(View view) {
        // Do something in response to button
    }

    In order for the system to match this method to the method name given to android:onClick, the signature must be exactly as shown. Specifically, the method must:

    • Be public
    • Have a void return value
    • Have a View as the only parameter (this will be the View that was clicked)

Next, you’ll fill in this method to read the contents of the text field and deliver that text to another activity.

Build an Intent


  1. In MyActivity.java, inside the sendMessage() method, create an Intent to start an activity called DisplayMessageActivity with the following code:

    java/com.mycompany.myfirstapp/MyActivity.java

    public void sendMessage(View view) {
      Intent intent = new Intent(this, DisplayMessageActivity.class);
    }

    Note: The reference to DisplayMessageActivity will raise an error if you’re using an IDE such as Android Studio because the class doesn’t exist yet. Ignore the error for now; you’ll create the class soon.

    The constructor used here takes two parameters:

    • A Context as its first parameter (this is used because the Activity class is a subclass of Context)
    • The Class of the app component to which the system should deliver the Intent (in this case, the activity that should be started)

    Android Studio indicates that you must import the Intent class.

  2. At the top of the file, import the Intent class:

    java/com.mycompany.myfirstapp/MyActivity.java

    import android.content.Intent;

    Tip: In Android Studio, press Alt + Enter (option + return on Mac) to import missing classes.

  3. Inside the sendMessage() method, use findViewById() to get the EditText element.

    java/com.mycompany.myfirstapp/MyActivity.java

    public void sendMessage(View view) {
      Intent intent = new Intent(this, DisplayMessageActivity.class);
      EditText editText = (EditText) findViewById(R.id.edit_message);
    }
  4. At the top of the file, import the EditText class.In Android Studio, press Alt + Enter (option + return on Mac) to import missing classes.
  5. Assign the text to a local message variable, and use the putExtra() method to add its text value to the intent.

    java/com.mycompany.myfirstapp/MyActivity.java

    public void sendMessage(View view) {
      Intent intent = new Intent(this, DisplayMessageActivity.class);
      EditText editText = (EditText) findViewById(R.id.edit_message);
      String message = editText.getText().toString();
      intent.putExtra(EXTRA_MESSAGE, message);
    }

    An Intent can carry data types as key-value pairs called extras. The putExtra() method takes the key name in the first parameter and the value in the second parameter.

  6. At the top of the MyActivity class, add the EXTRA_MESSAGE definition as follows:

    java/com.mycompany.myfirstapp/MyActivity.java

    public class MyActivity extends ActionBarActivity {
        public final static String EXTRA_MESSAGE = "com.mycompany.myfirstapp.MESSAGE";
        ...
    }

    For the next activity to query the extra data, you should define the key for your intent’s extra using a public constant. It’s generally a good practice to define keys for intent extras using your app’s package name as a prefix. This ensures the keys are unique, in case your app interacts with other apps.

  7. In the sendMessage() method, to finish the intent, call the startActivity() method, passing it the Intent object created in step 1.

With this new code, the complete sendMessage() method that’s invoked by the Send button now looks like this:

java/com.mycompany.myfirstapp/MyActivity.java

/** Called when the user clicks the Send button */
public void sendMessage(View view) {
    Intent intent = new Intent(this, DisplayMessageActivity.class);
    EditText editText = (EditText) findViewById(R.id.edit_message);
    String message = editText.getText().toString();
    intent.putExtra(EXTRA_MESSAGE, message);
    startActivity(intent);
}

The system receives this call and starts an instance of the Activity specified by the Intent. Now you need to create the DisplayMessageActivity class in order for this to work.

Create the Second Activity


All subclasses of Activity must implement the onCreate() method. This method is where the activity receives the intent with the message, then renders the message. Also, the onCreate() method must define the activity layout with the setContentView() method. This is where the activity performs the initial setup of the activity components.

Create a new activity using Android Studio

Figure 1. The new activity wizard in Android Studio.

Android Studio includes a stub for the onCreate() method when you create a new activity.

  1. In Android Studio, in the java directory, select the package, com.mycompany.myfirstapp, right-click, and select New > Activity > Blank Activity.
  2. In the Choose options window, fill in the activity details:
    • Activity Name: DisplayMessageActivity
    • Layout Name: activity_display_message
    • Title: My Message
    • Hierarchical Parent: com.mycompany.myfirstapp.MyActivity
    • Package name: com.mycompany.myfirstapp

    Click Finish.

  3. Open the DisplayMessageActivity.java file.The class already includes an implementation of the required onCreate() method. You will update the implementation of this method later. It also includes an implementation of onOptionsItemSelected(), which handles the action bar’s Up behavior. Keep these two methods as they are for now.
  4. Remove the onCreateOptionsMenu() method.You won’t need it for this app.

If you’re developing with Android Studio, you can run the app now, but not much happens. Clicking the Send button starts the second activity, but it uses a default “Hello world” layout provided by the template. You’ll soon update the activity to instead display a custom text view.

Create the activity without Android Studio

If you’re using a different IDE or the command line tools, do the following:

  1. Create a new file named DisplayMessageActivity.java in the project’s src/ directory, next to the original MyActivity.java file.
  2. Add the following code to the file:
    public class DisplayMessageActivity extends ActionBarActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_display_message);
    
            if (savedInstanceState == null) {
                getSupportFragmentManager().beginTransaction()
                    .add(R.id.container, new PlaceholderFragment()).commit();
            }
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
            if (id == R.id.action_settings) {
                return true;
            }
            return super.onOptionsItemSelected(item);
        }
    
        /**
         * A placeholder fragment containing a simple view.
         */
        public static class PlaceholderFragment extends Fragment {
    
            public PlaceholderFragment() { }
    
            @Override
            public View onCreateView(LayoutInflater inflater, ViewGroup container,
                      Bundle savedInstanceState) {
                  View rootView = inflater.inflate(R.layout.fragment_display_message,
                          container, false);
                  return rootView;
            }
        }
    }

    Note: If you are using an IDE other than Android Studio, your project does not contain the activity_display_message layout that’s requested by setContentView(). That’s OK because you will update this method later and won’t be using that layout.

  3. To your strings.xml file, add the new activity’s title as follows:
    <resources>
        ...
        <string name="title_activity_display_message">My Message</string>
    </resources>
  4. In your manifest file, AndroidManifest.xml, within the Application element, add the <activity> element for your DisplayMessageActivity class, as follows:
    <application ... >
        ...
        <activity
            android:name="com.mycompany.myfirstapp.DisplayMessageActivity"
            android:label="@string/title_activity_display_message"
            android:parentActivityName="com.mycompany.myfirstapp.MyActivity" >
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="com.mycompany.myfirstapp.MyActivity" />
        </activity>
    </application>

The android:parentActivityName attribute declares the name of this activity’s parent activity within the app’s logical hierarchy. The system uses this value to implement default navigation behaviors, such as Up navigation on Android 4.1 (API level 16) and higher. You can provide the same navigation behaviors for older versions of Android by using the Support Library and adding the <meta-data> element as shown here.

Note: Your Android SDK should already include the latest Android Support Library, which you installed during the Adding SDK Packages step. When using the templates in Android Studio, the Support Library is automatically added to your app project (you can see the library’s JAR file listed under Android Dependencies). If you’re not using Android Studio, you need to manually add the library to your project—follow the guide for setting up the Support Library then return here.

If you’re using a different IDE than Android Studio, don’t worry that the app won’t yet compile. You’ll soon update the activity to display a custom text view.

Receive the Intent


Every Activity is invoked by an Intent, regardless of how the user navigated there. You can get the Intent that started your activity by calling getIntent() and retrieve the data contained within the intent.

  1. In the java/com.mycompany.myfirstapp directory, edit the DisplayMessageActivity.java file.
  2. In the onCreate() method, remove the following line:
      setContentView(R.layout.activity_display_message);
  3. Get the intent and assign it to a local variable.
    Intent intent = getIntent();
  4. At the top of the file, import the Intent class.In Android Studio, press Alt + Enter (option + return on Mac) to import missing classes.
  5. Extract the message delivered by MyActivity with the getStringExtra() method.
    String message = intent.getStringExtra(MyActivity.EXTRA_MESSAGE);

Display the Message


  1. In the onCreate() method, create a TextView object.
    TextView textView = new TextView(this);
  2. Set the text size and message with setText().
    textView.setTextSize(40);
    textView.setText(message);
  3. Then add the TextView as the root view of the activity’s layout by passing it to setContentView().
    setContentView(textView);
  4. At the top of the file, import the TextView class.In Android Studio, press Alt + Enter (option + return on Mac) to import missing classes.

The complete onCreate() method for DisplayMessageActivity now looks like this:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Get the message from the intent
    Intent intent = getIntent();
    String message = intent.getStringExtra(MyActivity.EXTRA_MESSAGE);

    // Create the text view
    TextView textView = new TextView(this);
    textView.setTextSize(40);
    textView.setText(message);

    // Set the text view as the activity layout
    setContentView(textView);
}

You can now run the app. When it opens, type a message in the text field, click Send, and the message appears on the second activity.

Figure 2. Both activities in the final app, running on Android 4.4.

That’s it, you’ve built your first Android app!

Adding the Action Bar

Dependencies and prerequisites

  • Android 2.1 or higher

You should also read

Design Guide

Action Bar

The action bar is one of the most important design elements you can implement for your app’s activities. It provides several user interface features that make your app immediately familiar to users by offering consistency between other Android apps. Key functions include:

  • A dedicated space for giving your app an identity and indicating the user’s location in the app.
  • Access to important actions in a predictable way (such as Search).
  • Support for navigation and view switching (with tabs or drop-down lists).

This training class offers a quick guide to the action bar’s basics. For more information about action bar’s various features, see the Action Bar guide.

Lessons


Setting Up the Action Bar
Learn how to add a basic action bar to your activity, whether your app supports only Android 3.0 and higher or also supports versions as low as Android 2.1 (by using the Android Support Library).
Adding Action Buttons
Learn how to add and respond to user actions in the action bar.
Styling the Action Bar
Learn how to customize the appearance of your action bar.
Overlaying the Action Bar
Learn how to overlay the action bar in front of your layout, allowing for seamless transitions when hiding the action bar.

Setting Up the Action Bar

In its most basic form, the action bar displays the title for the activity and the app icon on the left. Even in this simple form, the action bar is useful for all activities to inform users about where they are and to maintain a consistent identity for your app.

Figure 1. An action bar with the app icon and activity title.

Setting up a basic action bar requires that your app use an activity theme that enables the action bar. How to request such a theme depends on which version of Android is the lowest supported by your app. So this lesson is divided into two sections depending on which Android version is your lowest supported.

Support Android 3.0 and Above Only


Beginning with Android 3.0 (API level 11), the action bar is included in all activities that use the Theme.Holo theme (or one of its descendants), which is the default theme when either the targetSdkVersion or minSdkVersion attribute is set to "11" or greater.

So to add the action bar to your activities, simply set either attribute to 11 or higher. For example:

<manifest ... >
    <uses-sdk android:minSdkVersion="11" ... />
    ...
</manifest>

Note: If you’ve created a custom theme, be sure it uses one of the Theme.Holo themes as its parent. For details, see Styling the Action Bar.

Now the Theme.Holo theme is applied to your app and all activities show the action bar. That’s it.

Support Android 2.1 and Above


Adding the action bar when running on versions older than Android 3.0 (down to Android 2.1) requires that you include the Android Support Library in your application.

To get started, read the Support Library Setup document and set up the v7 appcompat library (once you’ve downloaded the library package, follow the instructions for Adding libraries with resources).

Once you have the Support Library integrated with your app project:

  1. Update your activity so that it extends ActionBarActivity. For example:
    public class MainActivity extends ActionBarActivity { ... }
  2. In your manifest file, update either the <application> element or individual <activity> elements to use one of the Theme.AppCompat themes. For example:
    <activity android:theme="@style/Theme.AppCompat.Light" ... >

    Note: If you’ve created a custom theme, be sure it uses one of the Theme.AppCompat themes as its parent. For details, see Styling the Action Bar.

Now your activity includes the action bar when running on Android 2.1 (API level 7) or higher.

Remember to properly set your app’s API level support in the manifest:

<manifest ... >
    <uses-sdk android:minSdkVersion="7"  android:targetSdkVersion="18" />
    ...
</manifest>

 

Adding Action Buttons

The action bar allows you to add buttons for the most important action items relating to the app’s current context. Those that appear directly in the action bar with an icon and/or text are known as action buttons. Actions that can’t fit in the action bar or aren’t important enough are hidden in the action overflow.

Figure 1. An action bar with an action button for Search and the action overflow, which reveals additional actions.

Specify the Actions in XML


All action buttons and other items available in the action overflow are defined in an XML menu resource. To add actions to the action bar, create a new XML file in your project’s res/menu/ directory.

Add an <item> element for each item you want to include in the action bar. For example:

res/menu/main_activity_actions.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <!-- Search, should appear as action button -->
    <item android:id="@+id/action_search"
          android:icon="@drawable/ic_action_search"
          android:title="@string/action_search"
          android:showAsAction="ifRoom" />
    <!-- Settings, should always be in the overflow -->
    <item android:id="@+id/action_settings"
          android:title="@string/action_settings"
          android:showAsAction="never" />
</menu>

This declares that the Search action should appear as an action button when room is available in the action bar, but the Settings action should always appear in the overflow. (By default, all actions appear in the overflow, but it’s good practice to explicitly declare your design intentions for each action.)

The icon attribute requires a resource ID for an image. The name that follows @drawable/ must be the name of a bitmap image you’ve saved in your project’s res/drawable/ directory. For example, "@drawable/ic_action_search" refers to ic_action_search.png. Likewise, the title attribute uses a string resource that’s defined by an XML file in your project’s res/values/ directory, as discussed in Building a Simple User Interface.

Note: When creating icons and other bitmap images for your app, it’s important that you provide multiple versions that are each optimized for a different screen density. This is discussed more in the lesson about Supporting Different Screens.

If your app is using the Support Library for compatibility on versions as low as Android 2.1, the showAsAction attribute is not available from the android: namespace. Instead this attribute is provided by the Support Library and you must define your own XML namespace and use that namespace as the attribute prefix. (A custom XML namespace should be based on your app name, but it can be any name you want and is only accessible within the scope of the file in which you declare it.) For example:

res/menu/main_activity_actions.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:yourapp="http://schemas.android.com/apk/res-auto" >
    <!-- Search, should appear as action button -->
    <item android:id="@+id/action_search"
          android:icon="@drawable/ic_action_search"
          android:title="@string/action_search"
          yourapp:showAsAction="ifRoom"  />
    ...
</menu>

Add the Actions to the Action Bar


To place the menu items into the action bar, implement the onCreateOptionsMenu() callback method in your activity to inflate the menu resource into the given Menu object. For example:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu items for use in the action bar
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main_activity_actions, menu);
    return super.onCreateOptionsMenu(menu);
}

Respond to Action Buttons


When the user presses one of the action buttons or another item in the action overflow, the system calls your activity’s onOptionsItemSelected() callback method. In your implementation of this method, call getItemId() on the given MenuItem to determine which item was pressed—the returned ID matches the value you declared in the corresponding <item> element’s android:id attribute.

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle presses on the action bar items
    switch (item.getItemId()) {
        case R.id.action_search:
            openSearch();
            return true;
        case R.id.action_settings:
            openSettings();
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

Add Up Button for Low-level Activities


Figure 4. The Up button in Gmail.

All screens in your app that are not the main entrance to your app (activities that are not the “home” screen) should offer the user a way to navigate to the logical parent screen in the app’s hierarchy by pressing the Up button in the action bar.

When running on Android 4.1 (API level 16) or higher, or when using ActionBarActivity from the Support Library, performing Up navigation simply requires that you declare the parent activity in the manifest file and enable the Up button for the action bar.

For example, here’s how you can declare an activity’s parent in the manifest:

<application ... >
    ...
    <!-- The main/home activity (it has no parent activity) -->
    <activity
        android:name="com.example.myfirstapp.MainActivity" ...>
        ...
    </activity>
    <!-- A child of the main activity -->
    <activity
        android:name="com.example.myfirstapp.DisplayMessageActivity"
        android:label="@string/title_activity_display_message"
        android:parentActivityName="com.example.myfirstapp.MainActivity" >
        <!-- Parent activity meta-data to support 4.0 and lower -->
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.myfirstapp.MainActivity" />
    </activity>
</application>

Then enable the app icon as the Up button by calling setDisplayHomeAsUpEnabled():

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_displaymessage);

    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    // If your minSdkVersion is 11 or higher, instead use:
    // getActionBar().setDisplayHomeAsUpEnabled(true);
}

Because the system now knows MainActivity is the parent activity for DisplayMessageActivity, when the user presses the Up button, the system navigates to the parent activity as appropriate—you do not need to handle the Up button’s event.

For more information about up navigation, see Providing Up Navigation

Styling the Action Bar

The action bar provides your users a familiar and predictable way to perform actions and navigate your app, but that doesn’t mean it needs to look exactly the same as it does in other apps. If you want to style the action bar to better fit your product brand, you can easily do so using Android’s style and theme resources.

Android includes a few built-in activity themes that include “dark” or “light” action bar styles. You can also extend these themes to further customize the look for your action bar.

Note: If you are using the Support Library APIs for the action bar, then you must use (or override) the Theme.AppCompat family of styles (rather than the Theme.Holo family, available in API level 11 and higher). In doing so, each style property that you declare must be declared twice: once using the platform’s style properties (the android: properties) and once using the style properties included in the Support Library (the appcompat.R.attr properties—the context for these properties is actually your app). See the examples below for details.

Use an Android Theme


Android includes two baseline activity themes that dictate the color for the action bar:

You can apply these themes to your entire app or to individual activities by declaring them in your manifest file with the android:theme attribute for the <application> element or individual <activity> elements.

For example:

<application android:theme="@android:style/Theme.Holo.Light" ... />

You can also use a dark action bar while the rest of the activity uses the light color scheme by declaring the Theme.Holo.Light.DarkActionBar theme.

When using the Support Library, you must instead use the Theme.AppCompat themes:

Be sure that you use action bar icons that properly contrast with the color of your action bar. To help you, the Action Bar Icon Pack includes standard action icons for use with both the Holo light and Holo dark action bar.

Customize the Background


To change the action bar background, create a custom theme for your activity that overrides the actionBarStyle property. This property points to another style in which you can override the background property to specify a drawable resource for the action bar background.

If your app uses navigation tabs or the split action bar, then you can also specify the background for these bars using the backgroundStacked and backgroundSplit properties, respectively.

Caution: It’s important that you declare an appropriate parent theme from which your custom theme and style inherit their styles. Without a parent style, your action bar will be without many style properties unless you explicitly declare them yourself.

For Android 3.0 and higher only

When supporting Android 3.0 and higher only, you can define the action bar’s background like this:

res/values/themes.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- the theme applied to the application or activity -->
    <style name="CustomActionBarTheme"
           parent="@android:style/Theme.Holo.Light.DarkActionBar">
        <item name="android:actionBarStyle">@style/MyActionBar</item>
    </style>

    <!-- ActionBar styles -->
    <style name="MyActionBar"
           parent="@android:style/Widget.Holo.Light.ActionBar.Solid.Inverse">
        <item name="android:background">@drawable/actionbar_background</item>
    </style>
</resources>

Then apply your theme to your entire app or individual activities:

<application android:theme="@style/CustomActionBarTheme" ... />

For Android 2.1 and higher

When using the Support Library, the same theme as above must instead look like this:

res/values/themes.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- the theme applied to the application or activity -->
    <style name="CustomActionBarTheme"
           parent="@style/Theme.AppCompat.Light.DarkActionBar">
        <item name="android:actionBarStyle">@style/MyActionBar</item>

        <!-- Support library compatibility -->
        <item name="actionBarStyle">@style/MyActionBar</item>
    </style>

    <!-- ActionBar styles -->
    <style name="MyActionBar"
           parent="@style/Widget.AppCompat.Light.ActionBar.Solid.Inverse">
        <item name="android:background">@drawable/actionbar_background</item>

        <!-- Support library compatibility -->
        <item name="background">@drawable/actionbar_background</item>
    </style>
</resources>

Then apply your theme to your entire app or individual activities:

<application android:theme="@style/CustomActionBarTheme" ... />

Customize the Text Color


To modify the color of text in the action bar, you need to override separate properties for each text element:

For Android 3.0 and higher only

When supporting Android 3.0 and higher only, your style XML file might look like this:

res/values/themes.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- the theme applied to the application or activity -->
    <style name="CustomActionBarTheme"
           parent="@style/Theme.Holo">
        <item name="android:actionBarStyle">@style/MyActionBar</item>
        <item name="android:actionBarTabTextStyle">@style/MyActionBarTabText</item>
        <item name="android:actionMenuTextColor">@color/actionbar_text</item>
    </style>

    <!-- ActionBar styles -->
    <style name="MyActionBar"
           parent="@style/Widget.Holo.ActionBar">
        <item name="android:titleTextStyle">@style/MyActionBarTitleText</item>
    </style>

    <!-- ActionBar title text -->
    <style name="MyActionBarTitleText"
           parent="@style/TextAppearance.Holo.Widget.ActionBar.Title">
        <item name="android:textColor">@color/actionbar_text</item>
    </style>

    <!-- ActionBar tabs text styles -->
    <style name="MyActionBarTabText"
           parent="@style/Widget.Holo.ActionBar.TabText">
        <item name="android:textColor">@color/actionbar_text</item>
    </style>
</resources>

For Android 2.1 and higher

When using the Support Library, your style XML file might look like this:

res/values/themes.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- the theme applied to the application or activity -->
    <style name="CustomActionBarTheme"
           parent="@style/Theme.AppCompat">
        <item name="android:actionBarStyle">@style/MyActionBar</item>
        <item name="android:actionBarTabTextStyle">@style/MyActionBarTabText</item>
        <item name="android:actionMenuTextColor">@color/actionbar_text</item>

        <!-- Support library compatibility -->
        <item name="actionBarStyle">@style/MyActionBar</item>
        <item name="actionBarTabTextStyle">@style/MyActionBarTabText</item>
        <item name="actionMenuTextColor">@color/actionbar_text</item>
    </style>

    <!-- ActionBar styles -->
    <style name="MyActionBar"
           parent="@style/Widget.AppCompat.ActionBar">
        <item name="android:titleTextStyle">@style/MyActionBarTitleText</item>

        <!-- Support library compatibility -->
        <item name="titleTextStyle">@style/MyActionBarTitleText</item>
    </style>

    <!-- ActionBar title text -->
    <style name="MyActionBarTitleText"
           parent="@style/TextAppearance.AppCompat.Widget.ActionBar.Title">
        <item name="android:textColor">@color/actionbar_text</item>
        <!-- The textColor property is backward compatible with the Support Library -->
    </style>

    <!-- ActionBar tabs text -->
    <style name="MyActionBarTabText"
           parent="@style/Widget.AppCompat.ActionBar.TabText">
        <item name="android:textColor">@color/actionbar_text</item>
        <!-- The textColor property is backward compatible with the Support Library -->
    </style>
</resources>

Customize the Tab Indicator


To change the indicator used for the navigation tabs, create an activity theme that overrides the actionBarTabStyle property. This property points to another style resource in which you override the background property that should specify a state-list drawable.

Note: A state-list drawable is important so that the tab currently selected indicates its state with a background different than the other tabs. For more information about how to create a drawable resource that handles multiple button states, read the State List documentation.

For example, here’s a state-list drawable that declares a specific background image for several different states of an action bar tab:

res/drawable/actionbar_tab_indicator.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

<!-- STATES WHEN BUTTON IS NOT PRESSED -->

    <!-- Non focused states -->
    <item android:state_focused="false" android:state_selected="false"
          android:state_pressed="false"
          android:drawable="@drawable/tab_unselected" />
    <item android:state_focused="false" android:state_selected="true"
          android:state_pressed="false"
          android:drawable="@drawable/tab_selected" />

    <!-- Focused states (such as when focused with a d-pad or mouse hover) -->
    <item android:state_focused="true" android:state_selected="false"
          android:state_pressed="false"
          android:drawable="@drawable/tab_unselected_focused" />
    <item android:state_focused="true" android:state_selected="true"
          android:state_pressed="false"
          android:drawable="@drawable/tab_selected_focused" />


<!-- STATES WHEN BUTTON IS PRESSED -->

    <!-- Non focused states -->
    <item android:state_focused="false" android:state_selected="false"
          android:state_pressed="true"
          android:drawable="@drawable/tab_unselected_pressed" />
    <item android:state_focused="false" android:state_selected="true"
        android:state_pressed="true"
        android:drawable="@drawable/tab_selected_pressed" />

    <!-- Focused states (such as when focused with a d-pad or mouse hover) -->
    <item android:state_focused="true" android:state_selected="false"
          android:state_pressed="true"
          android:drawable="@drawable/tab_unselected_pressed" />
    <item android:state_focused="true" android:state_selected="true"
          android:state_pressed="true"
          android:drawable="@drawable/tab_selected_pressed" />
</selector>

For Android 3.0 and higher only

When supporting Android 3.0 and higher only, your style XML file might look like this:

res/values/themes.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- the theme applied to the application or activity -->
    <style name="CustomActionBarTheme"
           parent="@style/Theme.Holo">
        <item name="android:actionBarTabStyle">@style/MyActionBarTabs</item>
    </style>

    <!-- ActionBar tabs styles -->
    <style name="MyActionBarTabs"
           parent="@style/Widget.Holo.ActionBar.TabView">
        <!-- tab indicator -->
        <item name="android:background">@drawable/actionbar_tab_indicator</item>
    </style>
</resources>

For Android 2.1 and higher

When using the Support Library, your style XML file might look like this:

res/values/themes.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- the theme applied to the application or activity -->
    <style name="CustomActionBarTheme"
           parent="@style/Theme.AppCompat">
        <item name="android:actionBarTabStyle">@style/MyActionBarTabs</item>

        <!-- Support library compatibility -->
        <item name="actionBarTabStyle">@style/MyActionBarTabs</item>
    </style>

    <!-- ActionBar tabs styles -->
    <style name="MyActionBarTabs"
           parent="@style/Widget.AppCompat.ActionBar.TabView">
        <!-- tab indicator -->
        <item name="android:background">@drawable/actionbar_tab_indicator</item>

        <!-- Support library compatibility -->
        <item name="background">@drawable/actionbar_tab_indicator</item>
    </style>
</resources>

More resources

 

Overlaying the Action Bar

By default, the action bar appears at the top of your activity window, slightly reducing the amount of space available for the rest of your activity’s layout. If, during the course of user interaction, you want to hide and show the action bar, you can do so by calling hide() and show() on the ActionBar. However, this causes your activity to recompute and redraw the layout based on its new size.

Figure 1. Gallery’s action bar in overlay mode.

To avoid resizing your layout when the action bar hides and shows, you can enable overlay mode for the action bar. When in overlay mode, your activity layout uses all the space available as if the action bar is not there and the system draws the action bar in front of your layout. This obscures some of the layout at the top, but now when the action bar hides or appears, the system does not need to resize your layout and the transition is seamless.

Tip: If you want your layout to be partially visible behind the action bar, create a custom style for the action bar with a partially transparent background, such as the one shown in figure 1. For information about how to define the action bar background, read Styling the Action Bar.

Enable Overlay Mode


To enable overlay mode for the action bar, you need to create a custom theme that extends an existing action bar theme and set the android:windowActionBarOverlay property to true.

For Android 3.0 and higher only

If your minSdkVersion is set to 11 or higher, your custom theme should use Theme.Holo theme (or one of its descendants) as your parent theme. For example:

<resources>
    <!-- the theme applied to the application or activity -->
    <style name="CustomActionBarTheme"
           parent="@android:style/Theme.Holo">
        <item name="android:windowActionBarOverlay">true</item>
    </style>
</resources>

For Android 2.1 and higher

If your app is using the Support Library for compatibility on devices running versions lower than Android 3.0, your custom theme should use Theme.AppCompat theme (or one of its descendants) as your parent theme. For example:

<resources>
    <!-- the theme applied to the application or activity -->
    <style name="CustomActionBarTheme"
           parent="@android:style/Theme.AppCompat">
        <item name="android:windowActionBarOverlay">true</item>

        <!-- Support library compatibility -->
        <item name="windowActionBarOverlay">true</item>
    </style>
</resources>

Also notice that this theme includes two definitions for the windowActionBarOverlay style: one with the android: prefix and one without. The one with the android: prefix is for versions of Android that include the style in the platform and the one without the prefix is for older versions that read the style from the Support Library.

Specify Layout Top-margin


When the action bar is in overlay mode, it might obscure some of your layout that should remain visible. To ensure that such items remain below the action bar at all times, add either margin or padding to the top of the view(s) using the height specified by actionBarSize. For example:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="?android:attr/actionBarSize">
    ...
</RelativeLayout>

If you’re using the Support Library for the action bar, you need to remove the android: prefix. For example:

<!-- Support library compatibility -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="?attr/actionBarSize">
    ...
</RelativeLayout>

In this case, the ?attr/actionBarSize value without the prefix works on all versions, including Android 3.0 and higher.

Supporting Different Devices

Dependencies and prerequisites

  • Android 1.6 or higher

You should also read

Android devices come in many shapes and sizes all around the world. With a wide range of device types, you have an opportunity to reach a huge audience with your app. In order to be as successful as possible on Android, your app needs to adapt to various device configurations. Some of the important variations that you should consider include different languages, screen sizes, and versions of the Android platform.

This class teaches you how to use basic platform features that leverage alternative resources and other features so your app can provide an optimized user experience on a variety of Android-compatible devices, using a single application package (APK).

Lessons


Supporting Different Languages
Learn how to support multiple languages with alternative string resources.
Supporting Different Screens
Learn how to optimize the user experience for different screen sizes and densities.
Supporting Different Platform Versions
Learn how to use APIs available in new versions of Android while continuing to support older versions of Android.

Supporting Different Languages

It’s always a good practice to extract UI strings from your app code and keep them in an external file. Android makes this easy with a resources directory in each Android project.

If you created your project using the Android SDK Tools (read Creating an Android Project), the tools create a res/ directory in the top level of the project. Within this res/ directory are subdirectories for various resource types. There are also a few default files such as res/values/strings.xml, which holds your string values.

Create Locale Directories and String Files


To add support for more languages, create additional values directories inside res/ that include a hyphen and the ISO language code at the end of the directory name. For example, values-es/ is the directory containing simple resourcess for the Locales with the language code “es”. Android loads the appropriate resources according to the locale settings of the device at run time. For more information, see Providing Alternative Resources.

Once you’ve decided on the languages you will support, create the resource subdirectories and string resource files. For example:

MyProject/
    res/
       values/
           strings.xml
       values-es/
           strings.xml
       values-fr/
           strings.xml

Add the string values for each locale into the appropriate file.

At runtime, the Android system uses the appropriate set of string resources based on the locale currently set for the user’s device.

For example, the following are some different string resource files for different languages.

English (default locale), /values/strings.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="title">My Application</string>
    <string name="hello_world">Hello World!</string>
</resources>

Spanish, /values-es/strings.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="title">Mi Aplicación</string>
    <string name="hello_world">Hola Mundo!</string>
</resources>

French, /values-fr/strings.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="title">Mon Application</string>
    <string name="hello_world">Bonjour le monde !</string>
</resources>

Note: You can use the locale qualifier (or any configuration qualifer) on any resource type, such as if you want to provide localized versions of your bitmap drawable. For more information, see Localization.

Use the String Resources


You can reference your string resources in your source code and other XML files using the resource name defined by the <string> element’s name attribute.

In your source code, you can refer to a string resource with the syntax R.string.<string_name>. There are a variety of methods that accept a string resource this way.

For example:

// Get a string resource from your app's Resources
String hello = getResources().getString(R.string.hello_world);

// Or supply a string resource to a method that requires a string
TextView textView = new TextView(this);
textView.setText(R.string.hello_world);

In other XML files, you can refer to a string resource with the syntax @string/<string_name> whenever the XML attribute accepts a string value.

For example:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello_world" />


 

Supporting Different Screens

Android categorizes device screens using two general properties: size and density. You should expect that your app will be installed on devices with screens that range in both size and density. As such, you should include some alternative resources that optimize your app’s appearance for different screen sizes and densities.

  • There are four generalized sizes: small, normal, large, xlarge
  • And four generalized densities: low (ldpi), medium (mdpi), high (hdpi), extra high (xhdpi)

To declare different layouts and bitmaps you’d like to use for different screens, you must place these alternative resources in separate directories, similar to how you do for different language strings.

Also be aware that the screens orientation (landscape or portrait) is considered a variation of screen size, so many apps should revise the layout to optimize the user experience in each orientation.

Create Different Layouts


To optimize your user experience on different screen sizes, you should create a unique layout XML file for each screen size you want to support. Each layout should be saved into the appropriate resources directory, named with a -<screen_size> suffix. For example, a unique layout for large screens should be saved under res/layout-large/.

Note: Android automatically scales your layout in order to properly fit the screen. Thus, your layouts for different screen sizes don’t need to worry about the absolute size of UI elements but instead focus on the layout structure that affects the user experience (such as the size or position of important views relative to sibling views).

For example, this project includes a default layout and an alternative layout for large screens:

MyProject/
    res/
        layout/
            main.xml
        layout-large/
            main.xml

The file names must be exactly the same, but their contents are different in order to provide an optimized UI for the corresponding screen size.

Simply reference the layout file in your app as usual:

@Override
 protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);
}

The system loads the layout file from the appropriate layout directory based on screen size of the device on which your app is running. More information about how Android selects the appropriate resource is available in the Providing Resources guide.

As another example, here’s a project with an alternative layout for landscape orientation:

MyProject/
    res/
        layout/
            main.xml
        layout-land/
            main.xml

By default, the layout/main.xml file is used for portrait orientation.

If you want to provide a special layout for landscape, including while on large screens, then you need to use both the large and land qualifier:

MyProject/
    res/
        layout/              # default (portrait)
            main.xml
        layout-land/         # landscape
            main.xml
        layout-large/        # large (portrait)
            main.xml
        layout-large-land/   # large landscape
            main.xml

Note: Android 3.2 and above supports an advanced method of defining screen sizes that allows you to specify resources for screen sizes based on the minimum width and height in terms of density-independent pixels. This lesson does not cover this new technique. For more information, read Designing for Multiple Screens.

Create Different Bitmaps


You should always provide bitmap resources that are properly scaled to each of the generalized density buckets: low, medium, high and extra-high density. This helps you achieve good graphical quality and performance on all screen densities.

To generate these images, you should start with your raw resource in vector format and generate the images for each density using the following size scale:

  • xhdpi: 2.0
  • hdpi: 1.5
  • mdpi: 1.0 (baseline)
  • ldpi: 0.75

This means that if you generate a 200×200 image for xhdpi devices, you should generate the same resource in 150×150 for hdpi, 100×100 for mdpi, and 75×75 for ldpi devices.

Then, place the files in the appropriate drawable resource directory:

MyProject/
    res/
        drawable-xhdpi/
            awesomeimage.png
        drawable-hdpi/
            awesomeimage.png
        drawable-mdpi/
            awesomeimage.png
        drawable-ldpi/
            awesomeimage.png

Any time you reference @drawable/awesomeimage, the system selects the appropriate bitmap based on the screen’s density.

Note: Low-density (ldpi) resources aren’t always necessary. When you provide hdpi assets, the system scales them down by one half to properly fit ldpi screens.

For more tips and guidelines about creating icon assets for your app, see the Iconography design guide.

 

Supporting Different Platform Versions

While the latest versions of Android often provide great APIs for your app, you should continue to support older versions of Android until more devices get updated. This lesson shows you how to take advantage of the latest APIs while continuing to support older versions as well.

The dashboard for Platform Versions is updated regularly to show the distribution of active devices running each version of Android, based on the number of devices that visit the Google Play Store. Generally, it’s a good practice to support about 90% of the active devices, while targeting your app to the latest version.

Tip: In order to provide the best features and functionality across several Android versions, you should use the Android Support Library in your app, which allows you to use several recent platform APIs on older versions.

Specify Minimum and Target API Levels


The AndroidManifest.xml file describes details about your app and identifies which versions of Android it supports. Specifically, the minSdkVersion and targetSdkVersion attributes for the <uses-sdk element identify the lowest API level with which your app is compatible and the highest API level against which you’ve designed and tested your app.

For example:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" ... >
    <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="15" />
    ...
</manifest>

As new versions of Android are released, some style and behaviors may change. To allow your app to take advantage of these changes and ensure that your app fits the style of each user’s device, you should set the targetSdkVersion value to match the latest Android version available.

Check System Version at Runtime


Android provides a unique code for each platform version in the Build constants class. Use these codes within your app to build conditions that ensure the code that depends on higher API levels is executed only when those APIs are available on the system.

private void setUpActionBar() {
    // Make sure we're running on Honeycomb or higher to use ActionBar APIs
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        ActionBar actionBar = getActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
    }
}

Note: When parsing XML resources, Android ignores XML attributes that aren’t supported by the current device. So you can safely use XML attributes that are only supported by newer versions without worrying about older versions breaking when they encounter that code. For example, if you set the targetSdkVersion="11", your app includes the ActionBar by default on Android 3.0 and higher. To then add menu items to the action bar, you need to set android:showAsAction="ifRoom" in your menu resource XML. It’s safe to do this in a cross-version XML file, because the older versions of Android simply ignore the showAsAction attribute (that is, you do not need a separate version in res/menu-v11/).

Use Platform Styles and Themes


Android provides user experience themes that give apps the look and feel of the underlying operating system. These themes can be applied to your app within the manifest file. By using these built in styles and themes, your app will naturally follow the latest look and feel of Android with each new release.

To make your activity look like a dialog box:

<activity android:theme="@android:style/Theme.Dialog">

To make your activity have a transparent background:

<activity android:theme="@android:style/Theme.Translucent">

To apply your own custom theme defined in /res/values/styles.xml:

<activity android:theme="@style/CustomTheme">

To apply a theme to your entire app (all activities), add the android:theme attribute to the <application> element:

<application android:theme="@style/CustomTheme">

For more about creating and using themes, read the Styles and Themes guide.

 

Managing the Activity Lifecycle

Dependencies and prerequisites

You should also read

Try it out

Download the demo

ActivityLifecycle.zip

As a user navigates through, out of, and back to your app, the Activity instances in your app transition between different states in their lifecycle. For instance, when your activity starts for the first time, it comes to the foreground of the system and receives user focus. During this process, the Android system calls a series of lifecycle methods on the activity in which you set up the user interface and other components. If the user performs an action that starts another activity or switches to another app, the system calls another set of lifecycle methods on your activity as it moves into the background (where the activity is no longer visible, but the instance and its state remains intact).

Within the lifecycle callback methods, you can declare how your activity behaves when the user leaves and re-enters the activity. For example, if you’re building a streaming video player, you might pause the video and terminate the network connection when the user switches to another app. When the user returns, you can reconnect to the network and allow the user to resume the video from the same spot.

This class explains important lifecycle callback methods that each Activity instance receives and how you can use them so your activity does what the user expects and does not consume system resources when your activity doesn’t need them.

Lessons


Starting an Activity
Learn the basics about the activity lifecycle, how the user can launch your app, and how to perform basic activity creation.
Pausing and Resuming an Activity
Learn what happens when your activity is paused (partially obscured) and resumed and what you should do during these state changes.
Stopping and Restarting an Activity
Learn what happens when the user completely leaves your activity and returns to it.
Recreating an Activity
Learn what happens when your activity is destroyed and how you can rebuild the activity state when necessary.

Starting an Activity

Unlike other programming paradigms in which apps are launched with a main() method, the Android system initiates code in an Activity instance by invoking specific callback methods that correspond to specific stages of its lifecycle. There is a sequence of callback methods that start up an activity and a sequence of callback methods that tear down an activity.

This lesson provides an overview of the most important lifecycle methods and shows you how to handle the first lifecycle callback that creates a new instance of your activity.

Understand the Lifecycle Callbacks


During the life of an activity, the system calls a core set of lifecycle methods in a sequence similar to a step pyramid. That is, each stage of the activity lifecycle is a separate step on the pyramid. As the system creates a new activity instance, each callback method moves the activity state one step toward the top. The top of the pyramid is the point at which the activity is running in the foreground and the user can interact with it.

As the user begins to leave the activity, the system calls other methods that move the activity state back down the pyramid in order to dismantle the activity. In some cases, the activity will move only part way down the pyramid and wait (such as when the user switches to another app), from which point the activity can move back to the top (if the user returns to the activity) and resume where the user left off.

Figure 1. A simplified illustration of the Activity lifecycle, expressed as a step pyramid. This shows how, for every callback used to take the activity a step toward the Resumed state at the top, there’s a callback method that takes the activity a step down. The activity can also return to the resumed state from the Paused and Stopped state.

Depending on the complexity of your activity, you probably don’t need to implement all the lifecycle methods. However, it’s important that you understand each one and implement those that ensure your app behaves the way users expect. Implementing your activity lifecycle methods properly ensures your app behaves well in several ways, including that it:

  • Does not crash if the user receives a phone call or switches to another app while using your app.
  • Does not consume valuable system resources when the user is not actively using it.
  • Does not lose the user’s progress if they leave your app and return to it at a later time.
  • Does not crash or lose the user’s progress when the screen rotates between landscape and portrait orientation.

As you’ll learn in the following lessons, there are several situations in which an activity transitions between different states that are illustrated in figure 1. However, only three of these states can be static. That is, the activity can exist in one of only three states for an extended period of time:

Resumed
In this state, the activity is in the foreground and the user can interact with it. (Also sometimes referred to as the “running” state.)
Paused
In this state, the activity is partially obscured by another activity—the other activity that’s in the foreground is semi-transparent or doesn’t cover the entire screen. The paused activity does not receive user input and cannot execute any code.
Stopped
In this state, the activity is completely hidden and not visible to the user; it is considered to be in the background. While stopped, the activity instance and all its state information such as member variables is retained, but it cannot execute any code.

The other states (Created and Started) are transient and the system quickly moves from them to the next state by calling the next lifecycle callback method. That is, after the system calls onCreate(), it quickly calls onStart(), which is quickly followed by onResume().

That’s it for the basic activity lifecycle. Now you’ll start learning about some of the specific lifecycle behaviors.

Specify Your App’s Launcher Activity


When the user selects your app icon from the Home screen, the system calls the onCreate() method for the Activity in your app that you’ve declared to be the “launcher” (or “main”) activity. This is the activity that serves as the main entry point to your app’s user interface.

You can define which activity to use as the main activity in the Android manifest file, AndroidManifest.xml, which is at the root of your project directory.

The main activity for your app must be declared in the manifest with an <intent-filter> that includes the MAIN action and LAUNCHER category. For example:

<activity android:name=".MainActivity" android:label="@string/app_name">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

Note: When you create a new Android project with the Android SDK tools, the default project files include an Activity class that’s declared in the manifest with this filter.

If either the MAIN action or LAUNCHER category are not declared for one of your activities, then your app icon will not appear in the Home screen’s list of apps.

Create a New Instance


Most apps include several different activities that allow the user to perform different actions. Whether an activity is the main activity that’s created when the user clicks your app icon or a different activity that your app starts in response to a user action, the system creates every new instance of Activity by calling its onCreate() method.

You must implement the onCreate() method to perform basic application startup logic that should happen only once for the entire life of the activity. For example, your implementation of onCreate() should define the user interface and possibly instantiate some class-scope variables.

For example, the following example of the onCreate() method shows some code that performs some fundamental setup for the activity, such as declaring the user interface (defined in an XML layout file), defining member variables, and configuring some of the UI.

TextView mTextView; // Member variable for text view in the layout

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Set the user interface layout for this Activity
    // The layout file is defined in the project res/layout/main_activity.xml file
    setContentView(R.layout.main_activity);
    
    // Initialize member TextView so we can manipulate it later
    mTextView = (TextView) findViewById(R.id.text_message);
    
    // Make sure we're running on Honeycomb or higher to use ActionBar APIs
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        // For the main activity, make sure the app icon in the action bar
        // does not behave as a button
        ActionBar actionBar = getActionBar();
        actionBar.setHomeButtonEnabled(false);
    }
}

Caution: Using the SDK_INT to prevent older systems from executing new APIs works in this way on Android 2.0 (API level 5) and higher only. Older versions will encounter a runtime exception.

Once the onCreate() finishes execution, the system calls the onStart() and onResume() methods in quick succession. Your activity never resides in the Created or Started states. Technically, the activity becomes visible to the user when onStart() is called, but onResume() quickly follows and the activity remains in the Resumed state until something occurs to change that, such as when a phone call is received, the user navigates to another activity, or the device screen turns off.

In the other lessons that follow, you’ll see how the other start up methods, onStart() and onResume(), are useful during your activity’s lifecycle when used to resume the activity from the Paused or Stopped states.

Note: The onCreate() method includes a parameter called savedInstanceState that’s discussed in the latter lesson about Recreating an Activity.

Figure 2. Another illustration of the activity lifecycle structure with an emphasis on the three main callbacks that the system calls in sequence when creating a new instance of the activity: onCreate(), onStart(), and onResume(). Once this sequence of callbacks complete, the activity reaches the Resumed state where users can interact with the activity until they switch to a different activity.

Destroy the Activity


While the activity’s first lifecycle callback is onCreate(), its very last callback is onDestroy(). The system calls this method on your activity as the final signal that your activity instance is being completely removed from the system memory.

Most apps don’t need to implement this method because local class references are destroyed with the activity and your activity should perform most cleanup during onPause() and onStop(). However, if your activity includes background threads that you created during onCreate() or other long-running resources that could potentially leak memory if not properly closed, you should kill them during onDestroy().

@Override
public void onDestroy() {
    super.onDestroy();  // Always call the superclass
    
    // Stop method tracing that the activity started during onCreate()
    android.os.Debug.stopMethodTracing();
}

Note: The system calls onDestroy() after it has already called onPause() and onStop() in all situations except one: when you call finish() from within the onCreate() method. In some cases, such as when your activity operates as a temporary decision maker to launch another activity, you might call finish() from within onCreate() to destroy the activity. In this case, the system immediately calls onDestroy() without calling any of the other lifecycle methods.

Pausing and Resuming an Activity

This lesson teaches you to

  1. Pause Your Activity
  2. Resume Your Activity

You should also read

Try it out

Download the demo

ActivityLifecycle.zip

During normal app use, the foreground activity is sometimes obstructed by other visual components that cause the activity to pause. For example, when a semi-transparent activity opens (such as one in the style of a dialog), the previous activity pauses. As long as the activity is still partially visible but currently not the activity in focus, it remains paused.

However, once the activity is fully-obstructed and not visible, it stops (which is discussed in the next lesson).

As your activity enters the paused state, the system calls the onPause() method on your Activity, which allows you to stop ongoing actions that should not continue while paused (such as a video) or persist any information that should be permanently saved in case the user continues to leave your app. If the user returns to your activity from the paused state, the system resumes it and calls the onResume() method.

Note: When your activity receives a call to onPause(), it may be an indication that the activity will be paused for a moment and the user may return focus to your activity. However, it’s usually the first indication that the user is leaving your activity.

Figure 1. When a semi-transparent activity obscures your activity, the system calls onPause() and the activity waits in the Paused state (1). If the user returns to the activity while it’s still paused, the system calls onResume() (2).

Pause Your Activity


When the system calls onPause() for your activity, it technically means your activity is still partially visible, but most often is an indication that the user is leaving the activity and it will soon enter the Stopped state. You should usually use the onPause() callback to:

  • Stop animations or other ongoing actions that could consume CPU.
  • Commit unsaved changes, but only if users expect such changes to be permanently saved when they leave (such as a draft email).
  • Release system resources, such as broadcast receivers, handles to sensors (like GPS), or any resources that may affect battery life while your activity is paused and the user does not need them.

For example, if your application uses the Camera, the onPause() method is a good place to release it.

@Override
public void onPause() {
    super.onPause();  // Always call the superclass method first

    // Release the Camera because we don't need it when paused
    // and other activities might need to use it.
    if (mCamera != null) {
        mCamera.release()
        mCamera = null;
    }
}

Generally, you should not use onPause() to store user changes (such as personal information entered into a form) to permanent storage. The only time you should persist user changes to permanent storage within onPause() is when you’re certain users expect the changes to be auto-saved (such as when drafting an email). However, you should avoid performing CPU-intensive work during onPause(), such as writing to a database, because it can slow the visible transition to the next activity (you should instead perform heavy-load shutdown operations during onStop()).

You should keep the amount of operations done in the onPause() method relatively simple in order to allow for a speedy transition to the user’s next destination if your activity is actually being stopped.

Note: When your activity is paused, the Activity instance is kept resident in memory and is recalled when the activity resumes. You don’t need to re-initialize components that were created during any of the callback methods leading up to the Resumed state.

Resume Your Activity


When the user resumes your activity from the Paused state, the system calls the onResume() method.

Be aware that the system calls this method every time your activity comes into the foreground, including when it’s created for the first time. As such, you should implement onResume() to initialize components that you release during onPause() and perform any other initializations that must occur each time the activity enters the Resumed state (such as begin animations and initialize components only used while the activity has user focus).

The following example of onResume() is the counterpart to the onPause() example above, so it initializes the camera that’s released when the activity pauses.

@Override
public void onResume() {
    super.onResume();  // Always call the superclass method first

    // Get the Camera instance as the activity achieves full user focus
    if (mCamera == null) {
        initializeCamera(); // Local method to handle camera init
    }
}



Stopping and Restarting an Activity

This lesson teaches you to

  1. Stop Your Activity
  2. Start/Restart Your Activity

You should also read

Try it out

ActivityLifecycle.zip

Properly stopping and restarting your activity is an important process in the activity lifecycle that ensures your users perceive that your app is always alive and doesn’t lose their progress. There are a few of key scenarios in which your activity is stopped and restarted:

  • The user opens the Recent Apps window and switches from your app to another app. The activity in your app that’s currently in the foreground is stopped. If the user returns to your app from the Home screen launcher icon or the Recent Apps window, the activity restarts.
  • The user performs an action in your app that starts a new activity. The current activity is stopped when the second activity is created. If the user then presses the Back button, the first activity is restarted.
  • The user receives a phone call while using your app on his or her phone.

The Activity class provides two lifecycle methods, onStop() and onRestart(), which allow you to specifically handle how your activity handles being stopped and restarted. Unlike the paused state, which identifies a partial UI obstruction, the stopped state guarantees that the UI is no longer visible and the user’s focus is in a separate activity (or an entirely separate app).

Note: Because the system retains your Activity instance in system memory when it is stopped, it’s possible that you don’t need to implement the onStop() and onRestart() (or even onStart() methods at all. For most activities that are relatively simple, the activity will stop and restart just fine and you might only need to use onPause() to pause ongoing actions and disconnect from system resources.

Figure 1. When the user leaves your activity, the system calls onStop() to stop the activity (1). If the user returns while the activity is stopped, the system calls onRestart() (2), quickly followed by onStart() (3) and onResume() (4). Notice that no matter what scenario causes the activity to stop, the system always calls onPause() before calling onStop().

Stop Your Activity


When your activity receives a call to the onStop() method, it’s no longer visible and should release almost all resources that aren’t needed while the user is not using it. Once your activity is stopped, the system might destroy the instance if it needs to recover system memory. In extreme cases, the system might simply kill your app process without calling the activity’s final onDestroy() callback, so it’s important you use onStop() to release resources that might leak memory.

Although the onPause() method is called before onStop(), you should use onStop() to perform larger, more CPU intensive shut-down operations, such as writing information to a database.

For example, here’s an implementation of onStop() that saves the contents of a draft note to persistent storage:

@Override
protected void onStop() {
    super.onStop();  // Always call the superclass method first

    // Save the note's current draft, because the activity is stopping
    // and we want to be sure the current note progress isn't lost.
    ContentValues values = new ContentValues();
    values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText());
    values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle());

    getContentResolver().update(
            mUri,    // The URI for the note to update.
            values,  // The map of column names and new values to apply to them.
            null,    // No SELECT criteria are used.
            null     // No WHERE columns are used.
            );
}

When your activity is stopped, the Activity object is kept resident in memory and is recalled when the activity resumes. You don’t need to re-initialize components that were created during any of the callback methods leading up to the Resumed state. The system also keeps track of the current state for each View in the layout, so if the user entered text into an EditText widget, that content is retained so you don’t need to save and restore it.

Note: Even if the system destroys your activity while it’s stopped, it still retains the state of the View objects (such as text in an EditText) in a Bundle (a blob of key-value pairs) and restores them if the user navigates back to the same instance of the activity (the next lesson talks more about using a Bundle to save other state data in case your activity is destroyed and recreated).

Start/Restart Your Activity


When your activity comes back to the foreground from the stopped state, it receives a call to onRestart(). The system also calls the onStart() method, which happens every time your activity becomes visible (whether being restarted or created for the first time). The onRestart() method, however, is called only when the activity resumes from the stopped state, so you can use it to perform special restoration work that might be necessary only if the activity was previously stopped, but not destroyed.

It’s uncommon that an app needs to use onRestart() to restore the activity’s state, so there aren’t any guidelines for this method that apply to the general population of apps. However, because your onStop() method should essentially clean up all your activity’s resources, you’ll need to re-instantiate them when the activity restarts. Yet, you also need to instantiate them when your activity is created for the first time (when there’s no existing instance of the activity). For this reason, you should usually use the onStart() callback method as the counterpart to the onStop() method, because the system calls onStart() both when it creates your activity and when it restarts the activity from the stopped state.

For example, because the user might have been away from your app for a long time before coming back it, the onStart() method is a good place to verify that required system features are enabled:

@Override
protected void onStart() {
    super.onStart();  // Always call the superclass method first
    
    // The activity is either being restarted or started for the first time
    // so this is where we should make sure that GPS is enabled
    LocationManager locationManager = 
            (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    
    if (!gpsEnabled) {
        // Create a dialog here that requests the user to enable GPS, and use an intent
        // with the android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS action
        // to take the user to the Settings screen to enable GPS when they click "OK"
    }
}


@Override
protected void onRestart() {
    super.onRestart();  // Always call the superclass method first
    
    // Activity being restarted from stopped state    
}

When the system destroys your activity, it calls the onDestroy() method for your Activity. Because you should generally have released most of your resources with onStop(), by the time you receive a call to onDestroy(), there’s not much that most apps need to do. This method is your last chance to clean out resources that could lead to a memory leak, so you should be sure that additional threads are destroyed and other long-running actions like method tracing are also stopped.

Recreating an Activity

There are a few scenarios in which your activity is destroyed due to normal app behavior, such as when the user presses the Back button or your activity signals its own destruction by calling finish(). The system may also destroy your activity if it’s currently stopped and hasn’t been used in a long time or the foreground activity requires more resources so the system must shut down background processes to recover memory.

When your activity is destroyed because the user presses Back or the activity finishes itself, the system’s concept of that Activity instance is gone forever because the behavior indicates the activity is no longer needed. However, if the system destroys the activity due to system constraints (rather than normal app behavior), then although the actual Activity instance is gone, the system remembers that it existed such that if the user navigates back to it, the system creates a new instance of the activity using a set of saved data that describes the state of the activity when it was destroyed. The saved data that the system uses to restore the previous state is called the “instance state” and is a collection of key-value pairs stored in a Bundle object.

Caution: Your activity will be destroyed and recreated each time the user rotates the screen. When the screen changes orientation, the system destroys and recreates the foreground activity because the screen configuration has changed and your activity might need to load alternative resources (such as the layout).

By default, the system uses the Bundle instance state to save information about each View object in your activity layout (such as the text value entered into an EditText object). So, if your activity instance is destroyed and recreated, the state of the layout is restored to its previous state with no code required by you. However, your activity might have more state information that you’d like to restore, such as member variables that track the user’s progress in the activity.

Note: In order for the Android system to restore the state of the views in your activity, each view must have a unique ID, supplied by the android:id attribute.

To save additional data about the activity state, you must override the onSaveInstanceState() callback method. The system calls this method when the user is leaving your activity and passes it the Bundle object that will be saved in the event that your activity is destroyed unexpectedly. If the system must recreate the activity instance later, it passes the same Bundle object to both the onRestoreInstanceState() and onCreate() methods.

Figure 2. As the system begins to stop your activity, it calls onSaveInstanceState() (1) so you can specify additional state data you’d like to save in case the Activity instance must be recreated. If the activity is destroyed and the same instance must be recreated, the system passes the state data defined at (1) to both the onCreate() method (2) and the onRestoreInstanceState() method (3).

Save Your Activity State


As your activity begins to stop, the system calls onSaveInstanceState() so your activity can save state information with a collection of key-value pairs. The default implementation of this method saves information about the state of the activity’s view hierarchy, such as the text in an EditText widget or the scroll position of a ListView.

To save additional state information for your activity, you must implement onSaveInstanceState() and add key-value pairs to the Bundle object. For example:

static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save the user's current game state
    savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
    savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
    
    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
}

Caution: Always call the superclass implementation of onSaveInstanceState() so the default implementation can save the state of the view hierarchy.

Restore Your Activity State


When your activity is recreated after it was previously destroyed, you can recover your saved state from the Bundle that the system passes your activity. Both the onCreate() and onRestoreInstanceState() callback methods receive the same Bundle that contains the instance state information.

Because the onCreate() method is called whether the system is creating a new instance of your activity or recreating a previous one, you must check whether the state Bundle is null before you attempt to read it. If it is null, then the system is creating a new instance of the activity, instead of restoring a previous one that was destroyed.

For example, here’s how you can restore some state data in onCreate():

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); // Always call the superclass first
   
    // Check whether we're recreating a previously destroyed instance
    if (savedInstanceState != null) {
        // Restore value of members from saved state
        mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
        mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
    } else {
        // Probably initialize members with default values for a new instance
    }
    ...
}

Instead of restoring the state during onCreate() you may choose to implement onRestoreInstanceState(), which the system calls after the onStart() method. The system calls onRestoreInstanceState() only if there is a saved state to restore, so you do not need to check whether the Bundle is null:

public void onRestoreInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState);
stance
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
    mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}

Caution: Always call the superclass implementation of onRestoreInstanceState() so the default implementation can restore the state of the view hierarchy.

To learn more about recreating your activity due to a restart event at runtime (such as when the screen rotates), read Handling Runtime Changes.

Building a Dynamic UI with Fragments

Dependencies and prerequisites

You should also read

Try it out

Download the sample

FragmentBasics.zip

To create a dynamic and multi-pane user interface on Android, you need to encapsulate UI components and activity behaviors into modules that you can swap into and out of your activities. You can create these modules with the Fragment class, which behaves somewhat like a nested activity that can define its own layout and manage its own lifecycle.

When a fragment specifies its own layout, it can be configured in different combinations with other fragments inside an activity to modify your layout configuration for different screen sizes (a small screen might show one fragment at a time, but a large screen can show two or more).

This class shows you how to create a dynamic user experience with fragments and optimize your app’s user experience for devices with different screen sizes, all while continuing to support devices running versions as old as Android 1.6.

Lessons


Creating a Fragment
Learn how to build a fragment and implement basic behaviors within its callback methods.
Building a Flexible UI
Learn how to build your app with layouts that provide different fragment configurations for different screens.
Communicating with Other Fragments
Learn how to set up communication paths from a fragment to the activity and other fragments.

 

 

Creating a Fragment

This lesson teaches you to

  1. Create a Fragment Class
  2. Add a Fragment to an Activity using XML

You should also read

Try it out

Download the sample

FragmentBasics.zip

You can think of a fragment as a modular section of an activity, which has its own lifecycle, receives its own input events, and which you can add or remove while the activity is running (sort of like a “sub activity” that you can reuse in different activities). This lesson shows how to extend the Fragment class using the Support Library so your app remains compatible with devices running system versions as low as Android 1.6.

Note: If you decide that the minimum API level your app requires is 11 or higher, you don’t need to use the Support Library and can instead use the framework’s built in Fragment class and related APIs. Just be aware that this lesson is focused on using the APIs from the Support Library, which use a specific package signature and sometimes slightly different API names than the versions included in the platform.

Before you begin this lesson, you must set up your Android project to use the Support Library. If you have not used the Support Library before, set up your project to use the v4 library by following the Support Library Setup document. However, you can also include the action bar in your activities by instead using the v7 appcompat library, which is compatible with Android 2.1 (API level 7) and also includes the Fragment APIs.

Create a Fragment Class


To create a fragment, extend the Fragment class, then override key lifecycle methods to insert your app logic, similar to the way you would with an Activity class.

One difference when creating a Fragment is that you must use the onCreateView() callback to define the layout. In fact, this is the only callback you need in order to get a fragment running. For example, here’s a simple fragment that specifies its own layout:

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.ViewGroup;

public class ArticleFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.article_view, container, false);
    }
}

Just like an activity, a fragment should implement other lifecycle callbacks that allow you to manage its state as it is added or removed from the activity and as the activity transitions between its lifecycle states. For instance, when the activity’s onPause() method is called, any fragments in the activity also receive a call to onPause().

More information about the fragment lifecycle and callback methods is available in the Fragments developer guide.

Add a Fragment to an Activity using XML


While fragments are reusable, modular UI components, each instance of a Fragment class must be associated with a parent FragmentActivity. You can achieve this association by defining each fragment within your activity layout XML file.

Note: FragmentActivity is a special activity provided in the Support Library to handle fragments on system versions older than API level 11. If the lowest system version you support is API level 11 or higher, then you can use a regular Activity.

Here is an example layout file that adds two fragments to an activity when the device screen is considered “large” (specified by the large qualifier in the directory name).

res/layout-large/news_articles.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <fragment android:name="com.example.android.fragments.HeadlinesFragment"
              android:id="@+id/headlines_fragment"
              android:layout_weight="1"
              android:layout_width="0dp"
              android:layout_height="match_parent" />

    <fragment android:name="com.example.android.fragments.ArticleFragment"
              android:id="@+id/article_fragment"
              android:layout_weight="2"
              android:layout_width="0dp"
              android:layout_height="match_parent" />

</LinearLayout>

Tip: For more about creating layouts for different screen sizes, read Supporting Different Screen Sizes.

Then apply the layout to your activity:

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

public class MainActivity extends FragmentActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.news_articles);
    }
}

If you’re using the v7 appcompat library, your activity should instead extend ActionBarActivity, which is a subclass of FragmentActivity (for more information, read Adding the Action Bar).

Note: When you add a fragment to an activity layout by defining the fragment in the layout XML file, you cannot remove the fragment at runtime. If you plan to swap your fragments in and out during user interaction, you must add the fragment to the activity when the activity first starts, as shown in the next lesson.

Building a Flexible UI

When designing your application to support a wide range of screen sizes, you can reuse your fragments in different layout configurations to optimize the user experience based on the available screen space.

For example, on a handset device it might be appropriate to display just one fragment at a time for a single-pane user interface. Conversely, you may want to set fragments side-by-side on a tablet which has a wider screen size to display more information to the user.

Figure 1. Two fragments, displayed in different configurations for the same activity on different screen sizes. On a large screen, both fragments fit side by side, but on a handset device, only one fragment fits at a time so the fragments must replace each other as the user navigates.

The FragmentManager class provides methods that allow you to add, remove, and replace fragments to an activity at runtime in order to create a dynamic experience.

Add a Fragment to an Activity at Runtime


Rather than defining the fragments for an activity in the layout file—as shown in the previous lesson with the <fragment> element—you can add a fragment to the activity during the activity runtime. This is necessary if you plan to change fragments during the life of the activity.

To perform a transaction such as add or remove a fragment, you must use the FragmentManager to create a FragmentTransaction, which provides APIs to add, remove, replace, and perform other fragment transactions.

If your activity allows the fragments to be removed and replaced, you should add the initial fragment(s) to the activity during the activity’s onCreate() method.

An important rule when dealing with fragments—especially when adding fragments at runtime—is that your activity layout must include a container View in which you can insert the fragment.

The following layout is an alternative to the layout shown in the previous lesson that shows only one fragment at a time. In order to replace one fragment with another, the activity’s layout includes an empty FrameLayout that acts as the fragment container.

Notice that the filename is the same as the layout file in the previous lesson, but the layout directory does not have the large qualifier, so this layout is used when the device screen is smaller than large because the screen does not fit both fragments at the same time.

res/layout/news_articles.xml:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Inside your activity, call getSupportFragmentManager() to get a FragmentManager using the Support Library APIs. Then call beginTransaction() to create a FragmentTransaction and call add() to add a fragment.

You can perform multiple fragment transaction for the activity using the same FragmentTransaction. When you’re ready to make the changes, you must call commit().

For example, here’s how to add a fragment to the previous layout:

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

public class MainActivity extends FragmentActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.news_articles);

        // Check that the activity is using the layout version with
        // the fragment_container FrameLayout
        if (findViewById(R.id.fragment_container) != null) {

            // However, if we're being restored from a previous state,
            // then we don't need to do anything and should return or else
            // we could end up with overlapping fragments.
            if (savedInstanceState != null) {
                return;
            }

            // Create a new Fragment to be placed in the activity layout
            HeadlinesFragment firstFragment = new HeadlinesFragment();
            
            // In case this activity was started with special instructions from an
            // Intent, pass the Intent's extras to the fragment as arguments
            firstFragment.setArguments(getIntent().getExtras());
            
            // Add the fragment to the 'fragment_container' FrameLayout
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.fragment_container, firstFragment).commit();
        }
    }
}

Because the fragment has been added to the FrameLayout container at runtime—instead of defining it in the activity’s layout with a <fragment> element—the activity can remove the fragment and replace it with a different one.

Replace One Fragment with Another


The procedure to replace a fragment is similar to adding one, but requires the replace() method instead of add().

Keep in mind that when you perform fragment transactions, such as replace or remove one, it’s often appropriate to allow the user to navigate backward and “undo” the change. To allow the user to navigate backward through the fragment transactions, you must call addToBackStack() before you commit the FragmentTransaction.

Note: When you remove or replace a fragment and add the transaction to the back stack, the fragment that is removed is stopped (not destroyed). If the user navigates back to restore the fragment, it restarts. If you do not add the transaction to the back stack, then the fragment is destroyed when removed or replaced.

Example of replacing one fragment with another:

// Create fragment and give it an argument specifying the article it should show
ArticleFragment newFragment = new ArticleFragment();
Bundle args = new Bundle();
args.putInt(ArticleFragment.ARG_POSITION, position);
newFragment.setArguments(args);

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);

// Commit the transaction
transaction.commit();

The addToBackStack() method takes an optional string parameter that specifies a unique name for the transaction. The name isn’t needed unless you plan to perform advanced fragment operations using the FragmentManager.BackStackEntry APIs.

 

Communicating with Other Fragments

This lesson teaches you to

  1. Define an Interface
  2. Implement the Interface
  3. Deliver a Message to a Fragment

You should also read

Try it out

Download the sample

FragmentBasics.zip

In order to reuse the Fragment UI components, you should build each as a completely self-contained, modular component that defines its own layout and behavior. Once you have defined these reusable Fragments, you can associate them with an Activity and connect them with the application logic to realize the overall composite UI.

Often you will want one Fragment to communicate with another, for example to change the content based on a user event. All Fragment-to-Fragment communication is done through the associated Activity. Two Fragments should never communicate directly.

Define an Interface


To allow a Fragment to communicate up to its Activity, you can define an interface in the Fragment class and implement it within the Activity. The Fragment captures the interface implementation during its onAttach() lifecycle method and can then call the Interface methods in order to communicate with the Activity.

Here is an example of Fragment to Activity communication:

public class HeadlinesFragment extends ListFragment {
    OnHeadlineSelectedListener mCallback;

    // Container Activity must implement this interface
    public interface OnHeadlineSelectedListener {
        public void onArticleSelected(int position);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        
        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            mCallback = (OnHeadlineSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnHeadlineSelectedListener");
        }
    }
    
    ...
}

Now the fragment can deliver messages to the activity by calling the onArticleSelected() method (or other methods in the interface) using the mCallback instance of the OnHeadlineSelectedListener interface.

For example, the following method in the fragment is called when the user clicks on a list item. The fragment uses the callback interface to deliver the event to the parent activity.

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        // Send the event to the host activity
        mCallback.onArticleSelected(position);
    }

Implement the Interface


In order to receive event callbacks from the fragment, the activity that hosts it must implement the interface defined in the fragment class.

For example, the following activity implements the interface from the above example.

public static class MainActivity extends Activity
        implements HeadlinesFragment.OnHeadlineSelectedListener{
    ...
    
    public void onArticleSelected(int position) {
        // The user selected the headline of an article from the HeadlinesFragment
        // Do something here to display that article
    }
}

Deliver a Message to a Fragment


The host activity can deliver messages to a fragment by capturing the Fragment instance with findFragmentById(), then directly call the fragment’s public methods.

For instance, imagine that the activity shown above may contain another fragment that’s used to display the item specified by the data returned in the above callback method. In this case, the activity can pass the information received in the callback method to the other fragment that will display the item:

public static class MainActivity extends Activity
        implements HeadlinesFragment.OnHeadlineSelectedListener{
    ...

    public void onArticleSelected(int position) {
        // The user selected the headline of an article from the HeadlinesFragment
        // Do something here to display that article

        ArticleFragment articleFrag = (ArticleFragment)
                getSupportFragmentManager().findFragmentById(R.id.article_fragment);

        if (articleFrag != null) {
            // If article frag is available, we're in two-pane layout...

            // Call a method in the ArticleFragment to update its content
            articleFrag.updateArticleView(position);
        } else {
            // Otherwise, we're in the one-pane layout and must swap frags...

            // Create fragment and give it an argument for the selected article
            ArticleFragment newFragment = new ArticleFragment();
            Bundle args = new Bundle();
            args.putInt(ArticleFragment.ARG_POSITION, position);
            newFragment.setArguments(args);
        
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

            // Replace whatever is in the fragment_container view with this fragment,
            // and add the transaction to the back stack so the user can navigate back
            transaction.replace(R.id.fragment_container, newFragment);
            transaction.addToBackStack(null);

            // Commit the transaction
            transaction.commit();
        }
    }
}

[tute]; In this tutorial, we show you how to create a simple “hello world” Android project [rebl0g]

In this tutorial, we show you how to create a simple “hello world” Android project in Eclipse IDE + ADT plugin, and run it with Android Virtual Device (AVD). The Eclipse ADT plugin provided easy Android project creation and management, components drag and drop, auto-complete and many useful features to speed up your Android development cycles.

Summary steps to develop an Android application :

  1. Install Android SDK
  2. Install ADT Eclipse plugin
  3. Create an Android Virtual Device (AVD)
  4. Create Android Project with Eclipse (Wizard)
  5. Code it…
  6. Start it in Android Virtual Device (AVD)

Tools used in this tutorial :

  1. JDK 1.6
  2. Eclipse IDE 3.7 , Indigo
  3. Android SDK

1. Install Android SDK

Visit this Android SDK page, choose which platform and install it.

In Android SDK installed folder, run “Android SDK manager”, choose what Android version you want to develop.

android sdk manager

2. Install ADT Eclipse plugin

To integrate Android SDK with Eclipse IDE, you need to install Eclipse ADT plugin. Refer to this official guide – “Installing the ADT Plugin“.

In Eclipse IDE, select “Help” -> Install New Software…”, and put below URL :

https://dl-ssl.google.com/android/eclipse/
android ADT plugin
Note
In my case, above ADT plugin is taking years to download, no idea why. If you are facing the similar problem, just download and install the ADT plugin manually, refer to this ADT plugin troubleshooting guide.

3. Create an Android Virtual Device (AVD)

In Eclipse, you can access the “Android Virtual Device (AVD)” in Eclipse toolbar. Click “new” to create a AVD.

android avd manager

Later, Eclipse will deploy the application into this AVD.

4. Create Android Project

In Eclipse, select “File -> New -> Project….”, “Android Project”, and input your application detail. Eclipse will create all the necessary Android project files and configuration.

Eclipse new android project wizard
folder structure

5. Hello World

Locate the generated activity file, and modify a bit to output a string “Hello World”.

File : HelloWorldActivity.java

package com.mkyong.android;
 
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
 
public class HelloWorldActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        TextView text = new TextView(this);
        text.setText("Hello World, Android - mkyong.com");
        setContentView(text);
    }
}

6. Demo

Run it as “Android Application“, see output.

hello world output

Press “Home” button (on right hand side), and you will noticed that “HelloWorld” application is deployed successfully on the Android virtual device.

android deployed
Note
This tutorial is more to example driven, not much explanation. For detail and complete explanation, please refer to the official Android developer hello world tutorial.
Firewall…
In my computer, the COMODO firewall is installed and blocked the deploying process, caused the connection between Eclipse ADT and AVD is blocked and failed to deploy. Just make sure your firewall is configured properly, or just turn it off for Android development :)
Debug Android application on real device
Sometime, “Android Virtual Device” is not enough to test some real phone functionalities, like led light, sensor and etc. Then you should refer to this how to debug Android application on real device.

Download Source Code

Download it – Android-HelloWorld.zip (15 KB)

References

  1. Android Developers
Tags :

Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter, or befriend him on Facebook or Google Plus. If you like my tutorials, consider make a donation to these charities.

My website mkyong.com is hosted by Liquid Web, I really like their fast and helpful support, it saved me a lot of time. Furthermore, their servers are extremely reliable, fast and stable, I don’t remember when was the last time we had server downtime. Btw, they’re offering $100 Coupon now, if you are sourcing for great hosting provider, go grab it.

Related Posts

Popular Posts

You might also like following tutorials :

[tute]; This tutorial will show you how to debug Android application on a real Android-powered device (mobile phone). REBL0G

This tutorial will show you how to debug Android application on a real Android-powered device (mobile phone).

Tools and environment in this tutorial :

  1. Eclipse IDE 3.7 + ADT Plugin
  2. Samsung Galaxy S2
  3. Windows 7

Summary steps to debug on device :

  1. Download Google USB Driver (if using Android Developer Phones (ADP))
  2. Download OEM USB Drivers (if using other Android-powered device, Samsung, Acer, HTC…)
  3. In your device, turn on USB debugging.
  4. Connect your device to the PC.
  5. Use “adb devices” to verify that your device is connected successfully.
  6. Change Eclipse “Deployment Target Selection Mode” to “Manual”, and select the device at runtime.
  7. Done.

In this example, we will use the previous “Hello World Android Example“, and debug or run on a real Android-powered device, Samsung Galaxy S2.

1. Download OEM USB Driver

Refer to this Android USB driver guide. If you are using Android Developer Phones (ADP) like Nexus One or a Nexus S, you should install the Google USB driver via “Android SDK Manager“.

With Samsung Galaxy S2, you need to install OEM USB driver, or Samsung USB driver, which included in the Samsung Kies software.

Refer to this “where to download Samsung Galaxy S2 USB driver” guide to get USB driver install on your PC.

get samsung USB driver

2. Enable USB Debugging

In your device, to turn on USB debugging : “Settings” -> “Applications” -> “Development” -> “USB debugging”.

See figure below :

enable usb debugging on Android

3. Connect device to PC

Connect Samsung Galaxy S2 to the PC, and verify it via command “adb devices“.

In commmand prompt, change path to “Android SDK/platform-tools“, type command “adb devices“, if you see something like “some-weird-number device“, it means your device is connected to PC successfully.

Figure – The “304D19665059DF6E device” is the Samsung Galaxy S2.

adb devices

4. Eclipse -> Android

Note
Most people are stuck in this stage, beware.

Previously, you may created few “Android Virtual Devices (AVD)” for testing, and set “Deployment Target Selection Mode” to “Automatically“, however, this will caused the application failed to debug on your connected device and keep starting the AVD emulator.

2 solutions :

  1. In Eclipse right click on Android project, select “Run” -> “Run Configuration” -> “Android Application” -> “Target” tab -> “Deployment Target Selection Mode” -> set it to “Manual“, and you can select the device at runtime.
  2. Alternative, in “Deployment Target Selection Mode“, just deselect all the selected AVD.

Figure : Deployment Target Selection Mode

android eclipse deployment target

Figure : Select your device at runtime

select device at runtime

5. Start It

In Eclipse, run or debug your project as Android project, select your device at runtime and the project will copy to your Samsung Galaxy S2 and started automatically.

Figure : HelloWorldApp debugging on Samsung galaxy S2.

android hello world
android hello world

References

  1. Android developing on real device
  2. Android OEM USB driver
  3. Android debug on Samsung Galaxy S2
  4. Android hello world example

[mobile papers]; Wi-Fi Peer-to-Peer -rebl0g-

Wi-Fi Peer-to-Peer

Wi-Fi peer-to-peer (P2P) allows Android 4.0 (API level 14) or later devices with the appropriate hardware to connect directly to each other via Wi-Fi without an intermediate access point (Android’s Wi-Fi P2P framework complies with the Wi-Fi Alliance’s Wi-Fi Direct™ certification program). Using these APIs, you can discover and connect to other devices when each device supports Wi-Fi P2P, then communicate over a speedy connection across distances much longer than a Bluetooth connection. This is useful for applications that share data among users, such as a multiplayer game or a photo sharing application.

The Wi-Fi P2P APIs consist of the following main parts:

  • Methods that allow you to discover, request, and connect to peers are defined in the WifiP2pManager class.
  • Listeners that allow you to be notified of the success or failure of WifiP2pManager method calls. When calling WifiP2pManager methods, each method can receive a specific listener passed in as a parameter.
  • Intents that notify you of specific events detected by the Wi-Fi P2P framework, such as a dropped connection or a newly discovered peer.

You often use these three main components of the APIs together. For example, you can provide a WifiP2pManager.ActionListener to a call to discoverPeers(), so that you can be notified with the ActionListener.onSuccess() and ActionListener.onFailure() methods. A WIFI_P2P_PEERS_CHANGED_ACTION intent is also broadcast if the discoverPeers() method discovers that the peers list has changed.

API Overview


The WifiP2pManager class provides methods to allow you to interact with the Wi-Fi hardware on your device to do things like discover and connect to peers. The following actions are available:

Table 1.Wi-Fi P2P Methods

Method Description
initialize() Registers the application with the Wi-Fi framework. This must be called before calling any other Wi-Fi P2P method.
connect() Starts a peer-to-peer connection with a device with the specified configuration.
cancelConnect() Cancels any ongoing peer-to-peer group negotiation.
requestConnectInfo() Requests a device’s connection information.
createGroup() Creates a peer-to-peer group with the current device as the group owner.
removeGroup() Removes the current peer-to-peer group.
requestGroupInfo() Requests peer-to-peer group information.
discoverPeers() Initiates peer discovery
requestPeers() Requests the current list of discovered peers.

WifiP2pManager methods let you pass in a listener, so that the Wi-Fi P2P framework can notify your activity of the status of a call. The available listener interfaces and the corresponding WifiP2pManager method calls that use the listeners are described in the following table:

Table 2. Wi-Fi P2P Listeners

Listener interface Associated actions
WifiP2pManager.ActionListener connect(), cancelConnect(), createGroup(), removeGroup(), and discoverPeers()
WifiP2pManager.ChannelListener initialize()
WifiP2pManager.ConnectionInfoListener requestConnectInfo()
WifiP2pManager.GroupInfoListener requestGroupInfo()
WifiP2pManager.PeerListListener requestPeers()

The Wi-Fi P2P APIs define intents that are broadcast when certain Wi-Fi P2P events happen, such as when a new peer is discovered or when a device’s Wi-Fi state changes. You can register to receive these intents in your application by creating a broadcast receiver that handles these intents:

Table 3. Wi-Fi P2P Intents

Intent Description
WIFI_P2P_CONNECTION_CHANGED_ACTION Broadcast when the state of the device’s Wi-Fi connection changes.
WIFI_P2P_PEERS_CHANGED_ACTION Broadcast when you call discoverPeers(). You usually want to call requestPeers() to get an updated list of peers if you handle this intent in your application.
WIFI_P2P_STATE_CHANGED_ACTION Broadcast when Wi-Fi P2P is enabled or disabled on the device.
WIFI_P2P_THIS_DEVICE_CHANGED_ACTION Broadcast when a device’s details have changed, such as the device’s name.

Creating a Broadcast Receiver for Wi-Fi P2P Intents


A broadcast receiver allows you to receive intents broadcast by the Android system, so that your application can respond to events that you are interested in. The basic steps for creating a broadcast receiver to handle Wi-Fi P2P intents are as follows:

  1. Create a class that extends the BroadcastReceiver class. For the class’ constructor, you most likely want to have parameters for the WifiP2pManager, WifiP2pManager.Channel, and the activity that this broadcast receiver will be registered in. This allows the broadcast receiver to send updates to the activity as well as have access to the Wi-Fi hardware and a communication channel if needed.
  2. In the broadcast receiver, check for the intents that you are interested in onReceive(). Carry out any necessary actions depending on the intent that is received. For example, if the broadcast receiver receives a WIFI_P2P_PEERS_CHANGED_ACTION intent, you can call the requestPeers() method to get a list of the currently discovered peers.

The following code shows you how to create a typical broadcast receiver. The broadcast receiver takes a WifiP2pManager object and an activity as arguments and uses these two classes to appropriately carry out the needed actions when the broadcast receiver receives an intent:

/**
 * A BroadcastReceiver that notifies of important Wi-Fi p2p events.
 */
public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {

    private WifiP2pManager mManager;
    private Channel mChannel;
    private MyWiFiActivity mActivity;

    public WiFiDirectBroadcastReceiver(WifiP2pManager manager, Channel channel,
            MyWifiActivity activity) {
        super();
        this.mManager = manager;
        this.mChannel = channel;
        this.mActivity = activity;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();

        if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
            // Check to see if Wi-Fi is enabled and notify appropriate activity
        } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
            // Call WifiP2pManager.requestPeers() to get a list of current peers
        } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
            // Respond to new connection or disconnections
        } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
            // Respond to this device's wifi state changing
        }
    }
}

Creating a Wi-Fi P2P Application


Creating a Wi-Fi P2P application involves creating and registering a broadcast receiver for your application, discovering peers, connecting to a peer, and transferring data to a peer. The following sections describe how to do this.

Initial setup

Before using the Wi-Fi P2P APIs, you must ensure that your application can access the hardware and that the device supports the Wi-Fi P2P protocol. If Wi-Fi P2P is supported, you can obtain an instance of WifiP2pManager, create and register your broadcast receiver, and begin using the Wi-Fi P2P APIs.

    1. Request permission to use the Wi-Fi hardware on the device and also declare your application to have the correct minimum SDK version in the Android manifest:
      <uses-sdk android:minSdkVersion="14" />
      <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
      <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
      <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
      <uses-permission android:name="android.permission.INTERNET" />
      <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    2. Check to see if Wi-Fi P2P is on and supported. A good place to check this is in your broadcast receiver when it receives the WIFI_P2P_STATE_CHANGED_ACTION intent. Notify your activity of the Wi-Fi P2P state and react accordingly:
      @Override
      public void onReceive(Context context, Intent intent) {
          ...
          String action = intent.getAction();
          if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
              int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
              if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
                  // Wifi P2P is enabled
              } else {
                  // Wi-Fi P2P is not enabled
              }
          }
          ...
      }
    3. In your activity’s onCreate() method, obtain an instance of WifiP2pManager and register your application with the Wi-Fi P2P framework by calling initialize(). This method returns a WifiP2pManager.Channel, which is used to connect your application to the Wi-Fi P2P framework. You should also create an instance of your broadcast receiver with the WifiP2pManager and WifiP2pManager.Channel objects along with a reference to your activity. This allows your broadcast receiver to notify your activity of interesting events and update it accordingly. It also lets you manipulate the device’s Wi-Fi state if necessary:
      WifiP2pManager mManager;
      Channel mChannel;
      BroadcastReceiver mReceiver;
      ...
      @Override
      protected void onCreate(Bundle savedInstanceState){
          ...
          mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
          mChannel = mManager.initialize(this, getMainLooper(), null);
          mReceiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this);
          ...
      }
    4. Create an intent filter and add the same intents that your broadcast receiver checks for:
      IntentFilter mIntentFilter;
      ...
      @Override
      protected void onCreate(Bundle savedInstanceState){
          ...
          mIntentFilter = new IntentFilter();
          mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
          mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
          mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
          mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
          ...
      }
    5. Register the broadcast receiver in the onResume() method of your activity and unregister it in the onPause() method of your activity:
      /* register the broadcast receiver with the intent values to be matched */
      @Override
      protected void onResume() {
          super.onResume();
          registerReceiver(mReceiver, mIntentFilter);
      }
      /* unregister the broadcast receiver */
      @Override
      protected void onPause() {
          super.onPause();
          unregisterReceiver(mReceiver);
      }

      When you have obtained a WifiP2pManager.Channel and set up a broadcast receiver, your application can make Wi-Fi P2P method calls and receive Wi-Fi P2P intents.

You can now implement your application and use the Wi-Fi P2P features by calling the methods in WifiP2pManager. The next sections describe how to do common actions such as discovering and connecting to peers.

Discovering peers

To discover peers that are available to connect to, call discoverPeers() to detect available peers that are in range. The call to this function is asynchronous and a success or failure is communicated to your application with onSuccess() and onFailure() if you created a WifiP2pManager.ActionListener. The onSuccess() method only notifies you that the discovery process succeeded and does not provide any information about the actual peers that it discovered, if any:

mManager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
    @Override
    public void onSuccess() {
        ...
    }

    @Override
    public void onFailure(int reasonCode) {
        ...
    }
});

If the discovery process succeeds and detects peers, the system broadcasts the WIFI_P2P_PEERS_CHANGED_ACTION intent, which you can listen for in a broadcast receiver to obtain a list of peers. When your application receives the WIFI_P2P_PEERS_CHANGED_ACTION intent, you can request a list of the discovered peers with requestPeers(). The following code shows how to set this up:

PeerListListener myPeerListListener;
...
if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {

    // request available peers from the wifi p2p manager. This is an
    // asynchronous call and the calling activity is notified with a
    // callback on PeerListListener.onPeersAvailable()
    if (mManager != null) {
        mManager.requestPeers(mChannel, myPeerListListener);
    }
}

The requestPeers() method is also asynchronous and can notify your activity when a list of peers is available with onPeersAvailable(), which is defined in the WifiP2pManager.PeerListListener interface. The onPeersAvailable() method provides you with an WifiP2pDeviceList, which you can iterate through to find the peer that you want to connect to.

Connecting to peers

When you have figured out the device that you want to connect to after obtaining a list of possible peers, call the connect() method to connect to the device. This method call requires a WifiP2pConfig object that contains the information of the device to connect to. You can be notified of a connection success or failure through the WifiP2pManager.ActionListener. The following code shows you how to create a connection to a desired device:

//obtain a peer from the WifiP2pDeviceList
WifiP2pDevice device;
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = device.deviceAddress;
mManager.connect(mChannel, config, new ActionListener() {

    @Override
    public void onSuccess() {
        //success logic
    }

    @Override
    public void onFailure(int reason) {
        //failure logic
    }
});

Transferring data

Once a connection is established, you can transfer data between the devices with sockets. The basic steps of transferring data are as follows:

  1. Create a ServerSocket. This socket waits for a connection from a client on a specified port and blocks until it happens, so do this in a background thread.
  2. Create a client Socket. The client uses the IP address and port of the server socket to connect to the server device.
  3. Send data from the client to the server. When the client socket successfully connects to the server socket, you can send data from the client to the server with byte streams.
  4. The server socket waits for a client connection (with the accept() method). This call blocks until a client connects, so call this is another thread. When a connection happens, the server device can receive the data from the client. Carry out any actions with this data, such as saving it to a file or presenting it to the user.

The following example, modified from the Wi-Fi P2P Demo sample, shows you how to create this client-server socket communication and transfer JPEG images from a client to a server with a service. For a complete working example, compile and run the Wi-Fi P2P Demo sample.

public static class FileServerAsyncTask extends AsyncTask<void, void,="" string=""> {

    private Context context;
    private TextView statusText;

    public FileServerAsyncTask(Context context, View statusText) {
        this.context = context;
        this.statusText = (TextView) statusText;
    }

    @Override
    protected String doInBackground(Void... params) {
        try {

            /**
             * Create a server socket and wait for client connections. This
             * call blocks until a connection is accepted from a client
             */
            ServerSocket serverSocket = new ServerSocket(8888);
            Socket client = serverSocket.accept();

            /**
             * If this code is reached, a client has connected and transferred data
             * Save the input stream from the client as a JPEG file
             */
            final File f = new File(Environment.getExternalStorageDirectory() + "/"
                    + context.getPackageName() + "/wifip2pshared-" + System.currentTimeMillis()
                    + ".jpg");

            File dirs = new File(f.getParent());
            if (!dirs.exists())
                dirs.mkdirs();
            f.createNewFile();
            InputStream inputstream = client.getInputStream();
            copyFile(inputstream, new FileOutputStream(f));
            serverSocket.close();
            return f.getAbsolutePath();
        } catch (IOException e) {
            Log.e(WiFiDirectActivity.TAG, e.getMessage());
            return null;
        }
    }

    /**
     * Start activity that can handle the JPEG image
     */
    @Override
    protected void onPostExecute(String result) {
        if (result != null) {
            statusText.setText("File copied - " + result);
            Intent intent = new Intent();
            intent.setAction(android.content.Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.parse("file://" + result), "image/*");
            context.startActivity(intent);
        }
    }
}

On the client, connect to the server socket with a client socket and transfer data. This example transfers a JPEG file on the client device’s file system.

Context context = this.getApplicationContext();
String host;
int port;
int len;
Socket socket = new Socket();
byte buf[]  = new byte[1024];
...
try {
    /**
     * Create a client socket with the host,
     * port, and timeout information.
     */
    socket.bind(null);
    socket.connect((new InetSocketAddress(host, port)), 500);

    /**
     * Create a byte stream from a JPEG file and pipe it to the output stream
     * of the socket. This data will be retrieved by the server device.
     */
    OutputStream outputStream = socket.getOutputStream();
    ContentResolver cr = context.getContentResolver();
    InputStream inputStream = null;
    inputStream = cr.openInputStream(Uri.parse("path/to/picture.jpg"));
    while ((len = inputStream.read(buf)) != -1) {
        outputStream.write(buf, 0, len);
    }
    outputStream.close();
    inputStream.close();
} catch (FileNotFoundException e) {
    //catch logic
} catch (IOException e) {
    //catch logic
}

/**
 * Clean up any open sockets when done
 * transferring or if an exception occurred.
 */
finally {
    if (socket != null) {
        if (socket.isConnected()) {
            try {
                socket.close();
            } catch (IOException e) {
                //catch logic
            }
        }
    }
}