Latest Entries »

Android Preference Framework is among st the mostly widely used building blocks of Android. Almost every Android application makes use of the Preferences file in some way or the other and our app is no different.

Our app uses the Android Preferences to store some general keys like,

  • Hardware Make
  • Hardware Model
  • Software Version
  • Date
  • Time
  • Connection State

All the above mentioned values are being retrieved from a sensor and are stored by the App in the preferences, to be displayed to the User in a User Friendly Manner.  However, we ran into a weird problem which had its roots in the Android Preferences during one of our test-runs.

Superficially speaking about the problem, whenever the user tried to retrieve the above mentioned data from the Sensor, the process seemingly happened fine, but whenever the app was restarted after any such scenario, all of the previously stored data in the Preferences file was lost, i.e., the App behaved as a freshly installed app and being launched for the first time! We tried various lenses to view this problem, our most prominent lens(wild guess actually) being that somehow something was overwriting the preferences file to default settings. Another programmer also suggested that “Somehow the Preference object was being null“. We tried to be nice and please everybody by incorporating their hypothesis and applying the suggested fixes and ended up wasting like 2 hours over this so called conventional wisdom!

After blaming the Preference Framework for those 2 hours and interrogating the data associated with it, we could not extract anything meaningful out of it except the OnSharedPreferenceChangeListener. So we decided to find somebody else to blame for the mess being created and turned our attention to the Sensor framework(as the bug always popped out whenever the Sensor data was retrieved). After tracking the changes in the preferences via OnSharedPreferenceChangeListener, it became clear that the Sensor Framework was not only retrieving the data, but was also storing like 10 of those values in the Preferences in a rapid succession and the code doing this looked something like,

updatePreferences(key1, value1);

updatePreferences(key2, value2);

………..

updatePreferences(key10, value10);

As soon as this code was commented, the app behaved normally :-) .

This made us realize that it was not about Android Preferences but about the manner in which we were updating those and hence we derived a few cardinal rules about the same,

  • Shared Preferences are NOT designed for storing data which changes often and/or large amounts of data.
  • Shared Preferences are just a file – it has to be opened, parsed, updated and closed every time we do an update operation on it. Doing update operation in a rapid succession might just corrupt the file and restore it to default values which was our case exactly.
  • Do not access Shared Preferences from multiple threads.
  • ‘Conventional wisdom’ can be wrong.

Happy Coding!

Android ScrollView Trick

Recently I had a problem with one of my layouts, where I was trying to put a variable length content in a ScrollView. All I wanted was to keep the height of the ScrollView fixed, inspite of the length of the content. I was trying to avoid hardcoding the height parameter due to the obvious choice of multitude of the devices I wanted to cover with my layout(shown in figure below).
My initial attempts with the ScrollView(shown with a green highlight), were about messing with(a combination of) the height/width/fillViewPort parameters, but nothing helped. Since the content inside the ScrollView was getting rendered dynamically, the ScrollView used to extend and occupy more than the top-half of the screen and the price was payed by the controls contained in the bottom LinearLayout which just dissappeared. This was fixed by wrapping the bottom LinearLayout in a ScrollView(shown below) and weirdly, now the top ScrollView always rendered the dynamic content within the top half boundries, which was what I initially intended.

Genesis-1, Enjoying the View!

After uploading 2 casual gaming titles(Powered By And Engine: http://www.andengine.org/) on the Android Market(Search: Lunar Monk), We at Lunar Monk have been digging into the internals of the Android Graphics and Gaming capabilities(And Engine is good for your basic first game, but native is better). Our adventure begins from Replica Island (http://replicaisland.net/), One of the early games written for Android by Chris Pruett, which is open-source (http://code.google.com/p/replicaisland/) too. A read only copy can be checked out using Cygwin by giving the following command on Cygwin Bash,

svn checkout http://replicaisland.googlecode.com/svn/trunk/ replicaisland-read-only
 Just Make sure you have the svn package installed with Cygwin.
Our next step is building the Source, which is a bit of a daunting task due to this error: Conversion to Dalvik format failed with error 1. Let’s see how to eliminate this error.
First thing first, the source which is checked out is setup to be built on android 1.5 and as most of us know that there are not much of those android versions alive today, So we chose to build on android 4.0. But if we are configuring the project in Eclipse, then it is easy to spot that it fails to create R.java, which is due to the 2 anim files  activity_fade_in.xml & activity_fade_out.xml. Both the files use a linear interpolater for animation which is internal to android. To fix this, we need to create another xml with name linear_interpolator.xml. The contents of this xml would be,

<?xml version=”1.0″ encoding=”utf-8″?>
<linearInterpolator xmlns:android=”http://schemas.android.com/apk/res/android”/&gt;

Moving further we would be linking this xml to our activity_fade_in.xml & activity_fade_out.xml by changing the android:interpolator entry in these two files to, android:interpolator=”@anim/linear_interpolator”.Now cleaning the project and rebuilding it would result in successful compilation, but an attempt to install it on a device will result in the dreaded Conversion to Dalvik format failed with error 1. This is due to the fact because the compiler is confused due to the multiple entries/pointers to few classes being linked from different places in this project which is resulting in a path as well as name space conflict. To fix this, We need to first remove all the other jars included in Replica Island except the android.jar(Can be done by Right Click the Project -> Properties -> Java Build Path). Now we need to open the classpath file present in the project directory and replace its contents by,
<?xml version=”1.0″ encoding=”UTF-8″?>
<classpath>
<classpathentry kind=”src” path=”src”/>
<classpathentry kind=”src” path=”gen”/>
<classpathentry kind=”con” path=”com.android.ide.eclipse.adt.ANDROID_FRAMEWORK”/>
<classpathentry kind=”output” path=”bin”/>
</classpath>

Cleaning the project and rebuilding it now should fix the bug now.

However, If the dreaded error is seen again then this might be the cause(the fix is provided too): http://stackoverflow.com/questions/6683955/conversion-to-dalvik-format-failed-with-error-1-solution

The Blackberry platform offers the developer a few interesting choices if one wants to deleve deeper into the UI componenets. Here we see one such component known as the PictureScrollView. We use the PictureScrollView to design a screen which,

1. Contains a horizontal row of scrolling pictures in the top half of the screen, each one of which can be scrolled through or selected.

2. The lower half displays the enlarged picture which has been selected from the top half.

Our screen will have 3 small icon-pics in top half,

All in all, the UI(when center icon-pic is selected) will look like,

The Obvious part is that our PictureScrollScreen will extend from MainScreen.  The upper half of this screen will contain a PictureScrollField which would be containing an array of bitmaps. The lower half would be a BitmapField to display the enlarged Images. We would be intercepting the scroll event from the PictureScrollField by setting a FieldChangeListener onto it to achive the functionality,

/**
 * A class extending the MainScreen class, which provides default standard
 * behavior for BlackBerry GUI applications.
 */
public final class PictureScrollScreen extends MainScreen {
	int width = 0;
	int height = 0;
	static int count = 0;

	/**
 * Creates a new MyScreen object
 */
public PictureScrollScreen(int width, int height, long style) {
	// Set the displayed title of the screen
	super(style);
	((VerticalFieldManager) getMainManager())
			.setBackground(BackgroundFactory
					.createSolidBackground(Color.BLACK));
	this.setTitle("Picture Scroll");
	this.width = width;
	this.height = height;

	final Bitmap[] images = new Bitmap[3];
	String[] labels = new String[3];
	String[] tooltips = new String[3];

	images[0] = Bitmap.getBitmapResource("image1.jpg");
	labels[0] = "Label for image 1";
	tooltips[0] = "Tooltip for image 1";

	images[1] = Bitmap.getBitmapResource("image2.jpg");
	labels[1] = "Label for image 2";
	tooltips[1] = "Tooltip for image 2";

	images[2] = Bitmap.getBitmapResource("image3.jpg");
	labels[2] = "Label for image 3";
	tooltips[2] = "Tooltip for image 3";

	ScrollEntry[] entries = new ScrollEntry[3];
	for (int i = 0; i < entries.length; i++) {
		entries[i] = new ScrollEntry(images[i], labels[i], tooltips[i]);
	}

	final PictureScrollField pictureScrollField = new PictureScrollField(
			width / 2, height / 4);
	pictureScrollField.setData(entries, 0);
	pictureScrollField.setLabelsVisible(false);
	pictureScrollField
			.setHighlightStyle(HighlightStyle.ILLUMINATE_WITH_SHRINK_LENS);
	pictureScrollField.setHighlightBorderColor(Color.BLUE);

	pictureScrollField.setBackground(BackgroundFactory
			.createSolidBackground(Color.BLACK));

	/*
	 * PictureScrollField pictureScrollFieldBig = new
	 * PictureScrollField(width,(3*height)/4);
	 * pictureScrollFieldBig.setData(entries, 0);
	 * pictureScrollFieldBig.setLabelsVisible(false);
	 * pictureScrollFieldBig.setEnabled(false);
	 * pictureScrollFieldBig.setEditable(false);
	 * pictureScrollFieldBig.setCenteredLens(false);
	 * pictureScrollFieldBig.setImageDistance(1);
	 * pictureScrollFieldBig.setVisualState
	 * (Field.VISUAL_STATE_DISABLED_FOCUS);
	 * pictureScrollFieldBig.setBackground
	 * (BackgroundFactory.createSolidBackground(Color.BLACK));
	 */

		final int w = width;
		final int h = height / 2;
		Bitmap bmp = new Bitmap(w, h);
		images[0].scaleInto(bmp, Bitmap.FILTER_LANCZOS, Bitmap.SCALE_STRETCH);

		final BitmapField _bitmapField = new BitmapField(bmp, FIELD_HCENTER);
		_bitmapField.setBackground(BackgroundFactory
				.createSolidBackground(Color.BLACK));
		_bitmapField.setPadding(10, 5, 10, 5);

		pictureScrollField.setChangeListener(new FieldChangeListener() {
			public void fieldChanged(Field field, int context) {
				if (field == pictureScrollField) {
					int currentIndex = pictureScrollField
							.getCurrentImageIndex();
					Bitmap map = new Bitmap(w, h);
					images[currentIndex].scaleInto(map, Bitmap.FILTER_LANCZOS,
							Bitmap.SCALE_STRETCH);
					_bitmapField.setBitmap(map);
				}

			}
		});

		add(pictureScrollField);
		add(_bitmapField);
	}
}

So this is all about our little Salsa and Tango with the PictureScrollField. Hope you enjoyed it!

Feel free with any of your queries/doubts/improvements.

Android, Life of a ListView

The Listview in android could need a little getting used to if you are a newbie. I first met the listview while looking to design a custom list of items, which exhibits a unique behaviour classified into 2 categories,

1. All of items in the list would have a radiobutton and would be uniquely selectable.

2. A specific set of items would have an edit button(along with the radiobutton) & the item title would become editable if the edit button is clicked.

All in all I wanted my layout to look like,

list1

Above Image is a collection of those items which dos not have an edit button. Other set of that this list contains would look like,

list2

On selecting a particular item and then pressing the button, user would be greeted with an EditText Dialog as shown below,

list3

Let’s see step by step that how one should go about achieving this functionality

The primary requirement of the list in question is a listview. We can define a simple ListView in a listlayout.xml file,

<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:choiceMode="singleChoice"
android:id="@+id/triggerList"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:cacheColorHint="#00000000"
/>

Now the listview contains several row items, so to accomplish this we would be needing a row template which would define the layout of each row item. This can be defined in a file listrowtemplate.xml(Both the xml files will go inside the layout folder),

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent" android:layout_height="wrap_content"
	android:padding="5dip" android:orientation="horizontal"
	android:gravity="center_vertical">
	<RadioButton android:layout_width="wrap_content"
		android:layout_height="wrap_content" android:id="@+id/btn_radio" />

	<TextView android:id="@+id/triggerLabel" android:layout_width="fill_parent"
		android:layout_height="wrap_content" style="@style/BodyTextBigGrey"
		android:padding="5dip" android:gravity="center_horizontal|center_vertical"
		android:textSize="20dip" android:layout_weight="1" />
	<Button android:id="@+id/buttonEdit" android:layout_width="wrap_content"
		android:layout_height="wrap_content" android:text="Edit"
		android:layout_gravity="right" />
</LinearLayout>

Now,To take this further to the next level, One must know that a ListView exhibits an arcane property called as View Recycling i.e. The rows that are not getting displayed are recycled to save memory. Although sounding simple, this can sometimes become a bit dicey especially for custom lists(the one like ours) as we will need to maintain the state of our selected radio button if it undergoes the recycling process.

There can be numerous approaches to tackle this problem. We discuss one such approach here. We will need a model to main tain the current state of our rows & this is where the developer meets the Trigger class(Shakespere said, What’s in a Name?). The Trigger class is our model to maintain the state of various trigger rows added to our list. This is what the trigger class looks like,(Please mind that I’m posting the development code here and not the release one so one can always encounter a few trivial redundancies),

public class Trigger {

    private String triggerName;
    private boolean triggerStatus;
    protected TextView text;
    protected RadioButton radiobutton;
    protected Button button;

    public String getTriggerName() {
        return triggerName;
    }
    public void setTriggerName(String triggerName) {
        this.triggerName = triggerName;
    }
    public boolean getStatus() {
        return triggerStatus;
    }
    public void setStatus(boolean triggerStatus) {
        this.triggerStatus = triggerStatus;
    }
}

Now, Our ListView can maintain an ArrayList of these Triggers and we can also take care of the View Recycling process using the various getters and setters defined in our Trigger Class.
The bond between the ListView and its Data(Trigger items) is forged by something called as an Adapter. We would be needing a custom adapter class, to override its its getView method which has a signature like public View getView(final int position, View convertView, ViewGroup parent). Doing this would give us a fine control over the view recycling process because if a view has been recycled then the android system call the getView with convertView as null and this is how we would come to know that we need to reinstantiate that view and also restore it to its previous state i.e. as it was before recycling. Considering this, below is the implementation of our Trigger Adapter,

public class TriggerAdapter extends ArrayAdapter<Trigger> {

	private ArrayList<Trigger> items = null;
	private Context context = null;
	private String tracker = null;
	private ArrayList<Boolean> itemChecked = new ArrayList<Boolean>();

	public TriggerAdapter(Context context, int textViewResourceId,
			ArrayList<Trigger> items) {
		super(context, textViewResourceId, items);
		this.context = context;
		this.items = items;
		for (int i = 0; i < this.items.size(); i++) {
			itemChecked.add(i, false); // initializes all items value with false
		}
	}

public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
	LayoutInflater vi = (LayoutInflater) context
	.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
	v = vi.inflate(R.layout.listrowtemplate, null);
}
final Trigger trigger = items.get(position);
if (trigger != null) {
	trigger.text = (TextView) v.findViewById(R.id.triggerLabel);
	trigger.radiobutton = (RadioButton) v.findViewById(R.id.btn_radio);
	trigger.button = (Button) v.findViewById(R.id.buttonEdit);
	if (trigger.text != null) {

		trigger.text.setText(trigger.getTriggerName());
	}
	if (trigger.button != null) {
		if (position > 10) {
			trigger.button.setVisibility(View.VISIBLE);
		} else {
			trigger.button.setVisibility(View.INVISIBLE);
		}
	trigger.button.setOnClickListener(new OnClickListener() {
		public void onClick(View v) {
			final Trigger trigger = items.get(position);
			if (!trigger.getStatus()) {
				return;
			}
			AlertDialog.Builder alert = new AlertDialog.Builder(
					context);
			alert.setTitle("Title");
			alert.setMessage("Message");
			// Set an EditText view to get user input
			final EditText input = new EditText(context);
			alert.setView(input);
			alert.setPositiveButton("Ok",
					new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog,
						int whichButton) {
					String value = input.getText()
					.toString();
					// Do something with value!
					final Trigger trigger = items
					.get(position);
					trigger.setTriggerName(value);
					trigger.text.setText(value);
					items.remove(position);
					items.add(position, trigger);
				}
			});
			alert.setNegativeButton("Cancel",
					new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog,
						int whichButton) {
					// Canceled.
				}
			});

			alert.show();
			}
		});
	}
	if (trigger.radiobutton != null) {
		trigger.radiobutton.setChecked(trigger.getStatus());
		trigger.radiobutton.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
		     for (int i = 0; i < items.size(); i++) {
			final Trigger trig = items.get(i);
			if (trig.getStatus()) {
			trig.setStatus(false);
			trig.radiobutton.toggle();
			trig.radiobutton.invalidate();
			ListView list = (ListView) (((LinearLayout) v
						.getParent()).getParent());
			for (int j = 0; j < list.getChildCount(); j++) {
			LinearLayout l = (LinearLayout) list
			.getChildAt(j);
			RadioButton rd = (RadioButton) l
			.getChildAt(0);
			if (rd.isChecked()) {
				rd.setChecked(false);
			}
			}
			}
		}
				((RadioButton) v).setChecked(true);
				final Trigger trigger = items.get(position);
				trigger.setStatus(true);
				trigger.radiobutton.setChecked(true);
				items.remove(position);
				items.add(position, trigger);
			}
		});
	}
}
return v;

}

All in all, our list is now complete and we just need an activity with a button to display it(It actually depends on your choice how you want to display it), Mine is a simple activity with a button and on the click of the button the list is displayed,

On the click of the button, we actually create an AlertDialog and set the ListView as its content after populating it,

public class CustomListActivity extends Activity {

	private ArrayList<Trigger> mTriggers = null;
	private TriggerAdapter mAdapter = null;
	ListView list = null;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		((Button) findViewById(R.id.btn_list))
		.setOnClickListener(mClickListener);
	}

	protected void onStart() {
		super.onStart();
		String[] trigger_name = getResources().getStringArray(R.array.triggers);
		mTriggers = new ArrayList<Trigger>();
		for (int i = 0; i < trigger_name.length; i++) {
			final Trigger trigger = new Trigger();
			trigger.setTriggerName(trigger_name[i]);
			trigger.setStatus(false);
			mTriggers.add(trigger);
		}
		list = (ListView) getLayoutInflater()
		.inflate(R.layout.listlayout, null);
		list.setItemsCanFocus(true);
		list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);

	};

	OnClickListener mClickListener = new OnClickListener() {
		@Override
		public void onClick(final View view) {
			final AlertDialog.Builder builder = new AlertDialog.Builder(view
					.getContext());
			builder.setTitle(getResources().getString(R.string.trigger));
			mAdapter = new TriggerAdapter(CustomListActivity.this,
					R.layout.listrowtemplate, mTriggers);
			list.setAdapter(mAdapter);
			builder.setView(list);
			LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
					LinearLayout.LayoutParams.FILL_PARENT,
					LinearLayout.LayoutParams.WRAP_CONTENT);
			builder.setView(list);
			final AlertDialog alert = builder.create();
			if (!alert.isShowing()) {
				alert.show();
			}
		}
	};
}

So this was a bit about creating Custom Lists in android. Hope you enjoyed it.

If you have any questions/doubts/improvements, please feel free to post those.

A blob refers to a binary large object. A BLOB usually comes into picture with Sqlite, ususally it is some data(image, audio file) which needs to be stored in a database purely on need basis. Although it is not a very good approach to do this but some times it is just the requirement. So actually, I demonstrate here to store an icon image into the android sqlite as a BLOB(byte array) and then retrieve and show it on the screen.

 

  • Step 1 would be to convert the image into a byte array,

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon);

ByteArrayOutputStream bos = new ByteArrayOutputStream();

bitmap.compress(CompressFormat.PNG, 0 /*ignored for PNG*/, bos);

byte[] bitmapdata = bos.toByteArray();

 

  • Step 2 would be to store this in the database,

SQLiteDatabase db=this.openOrCreateDatabase(“imagedatabase”, this.MODE_PRIVATE,

null);

db.execSQL(“CREATE TABLE IF NOT EXISTS imagetable (“

+ “_id INTEGER PRIMARY KEY AUTOINCREMENT,”

+ “image BLOB”

+ “);”);

ContentValues values = new ContentValues();

values.put(“image”, bitmapdata);

long row_id=db.insert(“imagetable”, null, values);

 

  • Step 3 would be to retrieve and display it back on screen,

Cursor cursor =

db.query(“imagetable”, new String[]{“image”}, null, null,

null, null,null);

System.out.println(“—–getcolumn count”+cursor.moveToFirst());

//get it as a ByteArray

byte[] mybyte=cursor.getBlob(0);

//the cursor is not needed anymore

cursor.close();

//convert it back to an image

ByteArrayInputStream imageStream = new ByteArrayInputStream(mybyte);

Bitmap theImage = BitmapFactory.decodeStream(imageStream);

((ImageView)findViewById(R.id.view_image)).setImageBitmap(theImage);

A simple 3 step process!

OAuth! For those who come late, OAuth is a “standard” using which you as a developer can allow the user of your application to access his/her data which lies as a protected resource on the internet, in a trustworthy manner. Let’s say some module of your application needs the user to post a social update on facebook(maybe you wrote a really cool game and also included the facility to publish individual scores on facebook) . Now the end user may not be so comfortable(its all about trust baby!) to share his/her credentials with your application to publish the scores, Using Oauth, in this scenario you can leverage your application to a trusted one to post those updates.

Working of Oauth is pretty widely available on the net so I would not like to get in that.
Oauth can be a pretty daunting task for the first time, most of the time you make a simple “signed” request to fetch the data being requested from a “protected resource” and this at first usually results in an error “Invalid Oauth Signature”. Now any data when tormented enough is sure to confess, so I am just here to give you a few clues what could have gone wrong,

1. Do NOT go ahead implementing the OAuth signature algorithm from scratch. There are a lot of libraries available out there, Use those wisely and use those well.
2. Avoid using hardcoded timestamps and hardcoded nonce strings in the signature base strings.
3. The last and the most IMPORTANT one, the parameters being passed in the signature base string should be “alphabatically arranged”. Same should be done when including those parameters to the url being requested. This looks trivial but is VERY IMPORTANT.

The Burning Platform

In his letter mentioned at, http://tinyurl.com/4kxqjob, Stephen Elop, the current CEO of Nokia outlines and warns his employees that they are not only standing on a “burning platform” but are also pouring fuel onto it. For those, who have come late, the market share of nokia has been steadily dropping since 2008 and currently stands at 16%.

This, as compared to the market share of nokia in 2008 which was around 40%, indeed makes Nokia a “burning platform”.
But this brings me to the point, I’m not “very-very” much interested in the smartphone market, what caught my eye was the story that Stephen mentions, the story about the burning oil platform, a man in a really dicey situation and a “radical shift” in his behavior. “Radical Shift”, a term which means a sudden and tremendous change in the thinking process of a person arising due to some unforeseen circumstances, in the current context. We’ve been seeing radical shifts throughout history and it tells us that the person or entity that experiences these undergoes sudden fruitful transformation in comparatively minimal amount of time. Chris Gardner can be safely cited as one such example. Standing tall and pretty won’t get you very far and Nokia is a perfect example of this. To grow and to push beyond the limits, we all need these radical shifts from time to time. Nokia is just experiencing the same and the good part is that their CEO knows that.

Android SDK Tools

TraceView and mksdcard: TraceView is a very important tool bundled with the android sdk, which can let you trace various method calls present in your program. It can be of great help if you want to tweak the performance of your code.

To run traceview, you need a “.trace” file, this trace file can be created by your program code by calling,

Debug.startMethodTracing(“filename”), &,

Debug.stopMethodTracing()

You can call startMethodTracing(), in your onCreate() & stopMethodTracing() in onDestroy(), to record complete execution of your application code.

But, there’s a simple problem “.trace” files are created on the SD-Card of your android emulator. So before calling these methods you need to carry out 2 steps,

1. Create an SD-Card image.

2. Bind that SD-Card image to the emulator and run it from command line.

To create the SD-Card Image, the SDK has another bundled tool called as “mksdcard”,

Lets see the usage now,

1. Traverse to the tools folder of android,

2. Type in the command as, “mksdcard 100M mysdcard.img”

This will create an sd-card image file for your emulator, which will behave as a real sdcard.

3. Following command will bind the sd-card to the emulator and will launch it simultaneously.

Now your trace file is created and you need to pull it out from the android file system to your machine’s file system. For this, WITHOUT CLOSING THE EMULATOR, launch a new cmd and issue the following command from the tools folder,

adb pull /sdcard/myfile.trace myfile.trace

You can view the trace file by,

traceview myfile.trace

Powerful Intentions 2

There are a few ways in which one can launch intents,

First lets see how you create a basic intent,

new Intent(context, helloactivity.class);

Above is an example of an explicit intent which does not require any intent filter to be present in the android manifest, as the target activity has already been specified as the second parameter.

Another way can be,

new Intent(Intent.ACTION_VIEW,uri);

The uri plays an important role here as described below,

  1. http: or https:, will display a link in the browser.
  2. ge0: used to perform google maps related stuff on appropriately supplied longitude and latitude
  3. tel: or voicemail: for telephony stuff
Follow

Get every new post delivered to your Inbox.

Join 28 other followers