Thursday, December 16, 2010
Improved Copy/Paste in Gingerbread
Here's the link where you can find out more about this.
Some images and videos
Official documentation
You need to double-tap on the text before you can bring up the text selection controls. Once you are done with the selection, single tap on the text copies the selected text to the clipboard, and then you can extract the data from the clipboard. This is really nice. Else, you would have to write a bit of extra code to trigger text selection mode first. This copy/paste selector works on an EditText and on the Browser. I haven't tested it further.
Gingerbread Stuff!!!! **It works on the emulator**.
Wednesday, November 17, 2010
Getting animations to work
In this example, there is an ImageView with it's "src" value set to an image. The ImageView's background is set with you own AnimationDrawable, basically an xml in your res/drawable folder. In the activity, the ImageView has a click listener, which creates an AnimationDrawable from the ImageView's background, and just calls the start method of the AnimationDrawable class.
Here is a sample AnimationDrawable described through XML.
<?xml version="1.0" encoding="utf-8"?>And here is the code that gets your animation started.
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/black" android:duration="200" />
<item android:drawable="@drawable/cyan" android:duration="200" />
<item android:drawable="@drawable/green" android:duration="200" />
<item android:drawable="@drawable/magenta" android:duration="200" />
<item android:drawable="@drawable/navy" android:duration="200" />
<item android:drawable="@drawable/orange" android:duration="200" />
<item android:drawable="@drawable/pink" android:duration="200" />
<item android:drawable="@drawable/white" android:duration="200" />
<item android:drawable="@drawable/yellow" android:duration="200" />
</animation-list>
imageView = (ImageView) findViewById(R.id.ImageButton01);One point to notice is that, you have to remove the ImageView's "src" value, so that the animation is visible, since the animation works by changing the background of the ImageView, else, your animation would be blocked by the ImageView's "src" image.
imageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
AnimationDrawable animator = (AnimationDrawable) imageView.getBackground();
imageView.setImageDrawable(null);
animator.start();
}
});
Once you are done, you can stop the animation, and reset the ImageView's "src" to it's original image.
// Call this method to stop the animationYou can find the whole source code for this example here.
public void stopAnimation(){
AnimationDrawable animator = (AnimationDrawable) imageView.getBackground();
animator.stop();
imageView.setImageResource(R.drawable.icon);
}
Monday, October 25, 2010
Unzip files in Android
This example shows you how to unzip a zip file through these classes. If you want to create zip files, that's also possible, but we will keep it for later. In this project, there is a zip file, called ZipTest.zip in the assets folder. It's pretty easy to pick up any zip file on your phone through code. For simplicity, I have placed out test file in the assets folder.
The code is simple enough to need any more explanations. I have put comments in the code. So, do check it out and run it. I have logged the steps on the Activity.
Note: There's not much error handling code put in place.
Wednesday, October 20, 2010
Android WebView, Javascript and CSS
1. CSS: Applying CSS is just the same as you would do with normal HTML pages. The sample_page.html in the assets folder refers to the sample_style.css file in the same folder. One thing you might notice is how we get the rounder corners for the divs. This CSS attribute does the trick.
-webkit-border-radius: 5px;2. Javascript: To make it simpler, I have used the JQuery library. The mobile version released recently gave some errors. So, I have used the normal library available. The jquery-1.4.2.min.js also resides in the assets folder and is referenced in the sample_page.html.
3. All together: In the sample_page.html I have a header, a body and the controls. The controls have four buttons
a: JToggle: This toggles the visibility of the body section. This is a pure javascript method call from the html.
b: NToggle: This also toggles the visibility of the body section. But it does it differently. The javascript calls to the JSInterface.java method, which in turn calls the same Javascript method.
c. Exit: This button basically closes/exits the app, by calling the JSInterface.java method which is bound to the HomeActivity.java via OnExitAppListener.java
d. Alert: This shows an alert which is basically an AlertDialog in Android.
Calling a Javascript method from your Java code:
webView.loadUrl("javascript:jsToggle()");
Calling a Java method from Javascript:
window.jsinterface.nativeToggle();
/*
// Before using the above code, you have to inject the interface object which
// has a name "jsinterface"
webView.addJavascriptInterface(jsInterface, "jsinterface");
*/
Controlling the Alerts from Javascript:
The SampleChromeClient.java which extends the WebChromeClient has several methods which provide hooks which allow you to customize their behaviour. For an example, you can override the behaviour of the alert function and do whatever you want. You can show your own dialog with Yes/No buttons and depending on the input, you can send back the result to your Javascript code.
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result)
{
url = "Sample App Alert";
return super.onJsAlert(view, url, message, result);
}
You can checkout the whole source code here. It's ready to run. Let me know if you have any issues.
Friday, October 15, 2010
More security for your Android
What could this API do?
Using these APIs, the IT-Admins can install a Admin App, which enforces system wide security policies.
- Enable Passwords (Only lock screen as of now)
- Set minimum password length
- Alphanumeric password required
- Maximum password attempts
- Maximum inactivity time lock
- Lock device immediately
- Wipe the device data (to factory settings) (Remote/Local)
The key to all these features are that you have to have that admin app installed and activated as well. Also, you can have multiple admin apps that enforce multiple security policies. In situations of clash, the most strict policy will be enforced. This admin app controls how your device behaves in different situations. You can set parameters as to when and under what conditions your device should be wiped out. Say, after 20 failed password attempts, you want to wipe out the data to factory settings, the Admin app can do this using the Device Administration API.
For more information and samples on how to start with this API, visit the official documentation here.
With more and more features being packed into Android, now it is probably targeting the enterprises. Not having a way of enforcing such policies have indeed been a setback for Android to entice the Business users, but now, I can hear them come running. :D
Friday, September 17, 2010
ExpandableListView on Android
As with any other widget on Android, you are free to customize the widgets as per your needs. Here, I will show how to create such a custom list adapter for the ExpandableListView.
For this example, I want to show a list of vehicles with their names. Also, I want to group them according to their category.
I have 4 classes.
1. Vehicle : The parent class for the rest.
2. Car: Extends the Vehicle class.
3. Bus: Extends the Vehicle class.
4. Bike: Extends the Vehicle class.
I have a method called getRandomVehicle(String name) which returns a random vehicle instance setting the name that I pass. The vehicle can be a Bus, Car or a Bike. Its completely random.
In the ExpandableListAdapter, (the custom adapter), there's a method called addItem(Vehicle vehicle), which manages the groups and their children.
In the SampleActivity, I have initialized a blank ExpandableListAdapter and set it to the list view. Now, I start a thread, which gets a random vehicle after every 2 seconds, and adds it to the adapter, and calls the adapter to notify that the data has changed.
There are a few methods, in the ExpandableListAdapter, which you should go through carefully. I have two layout files, group_layout.xml and child_layout.xml which are used as the layout for the group views and the child views of the ExpandableListView.
There you go, you have a custom ExpandableListView. You can find the full source code for this example here, ready to run.
There are some more methods that you might be interested in, like, how to change the "arrow icon" for the group views(official doc link), or how to expand or collapse a group at will, or how to handle specific events like group collapsed or group expanded. Read the docs on ExpandableListView.
Monday, September 13, 2010
SDK Tools - ADT Plugin updated
After you update the SDK tools(r7) from the Android SDK manager or otherwise, you would be prompted to update the ADT plugin(0.9.8) as well. Go for it, and you will see quite a few changes.
In the SDK Tools:
http://developer.android.com/sdk/tools-notes.html
In the ADT Plugin:
http://developer.android.com/sdk/eclipse-adt.html
For SDK Tools
- Support for library projects.
- Support for aidl files in library projects
- Support for extension targets in Ant build to perform tasks between the normal tasks
- Support for "headless" SDK update
- Fixes location control in DDMS to work in any locale not using '.' as a decimal point
For ADT Plugin
- Rename package : One click change of project's package
- Support for library projects that don't have a source folder called
src/
-
Support for library projects that depend on other library projects-
Support for additional resource qualifiers: car
/desk
, night
/notnight
and navexposed
/navhidden
-
Adds more device screen types in the layout editor. (Nice)-
Fixes problems with handling of library project namesThe most important update for me is the inclusion of more layout editor configurations by default. My last post on creating different configurations for different screen sizes here was just an example to create a configuration for working with different screen sizes at design time. It's a bonus that they are now included in there by default.
Once click package renaming is also a nice feature, in case you want to fork your project into different versions. Check them out.
Sunday, September 5, 2010
Getting started with Tablets - They are coming
First of all, you need to setup a few tablet emulators for your apps. This bit is rather simple. Create a new AVD. I guess this screenshot explains the rest. For some reasons, I have not been able to create Tablet AVDs on 1.6. But it definitely works on Android 2.2 (Froyo).
After you create this AVD, fire it up. And you should be able to see the Droid up and jumping.
You can now test out your apps on this tablet emulator. Well, since tablet devices will obviously come under large-screens, to make your designing layouts for large screens easy, you need to tweak up a few things on eclipse. Since, large screen devices take up the xml layouts from the "layout-large" and "layout-large-land" folders, if it all you have different layouts for large screens, to visualize your designs during your development, you need to add one more configuration for large screens.
Steps to add a new configuration
- Open eclipse. Open any layout xml, so that you can get to the screen where you can add a custom configuration.
- In the devices drop down, select custom to create a new configuration. Click on "Create" which will open up the configuration screen.
- On the new configuration screen, select "Nexus One" and click on "Copy" to create a copy which you can edit later.
- Once you get a copy, you can rename it to your own configuration name.
- Before you are done, you need to change a few values for both the layouts, landscape and portrait. Follow the screen shot.
Change x dpi, y dpi, Screen Size, Resolution and set it to values as shown above. Do it for both the orientations.
- Save the configuration. Now, whenever you change the configuration to your custom config, since this custom config is for the large screen devices, it would show you how your layouts will look on a real device. It will pick up the xml files correctly whenever you switch your configuration to large screens.
Monday, August 9, 2010
Android OS Versions in the Wild
Image Source : http://developer.android.com/resources/dashboard/platform-versions.html
The above chart gives us an idea of the overall OS spread (August 2, 2010). 59.7% of the Android phones are now running on Android 2.1(Donut). Isn't that great. Nice. And we will definitely see the percentage for Android 2.2(Froyo) increase manifold when manufacturers push updates on the latest version. But, there is a substantial amount of phones still out there running on 1.5, though not a majority. But, if we talk about only numbers, 20.3% of the total Android phones is still a huge number. Now that's a problem.
With Android 1.6 and up, apps can be designed and developed for different density and screen resolutions. The cupcake update doesn't have this feature. There are a few workarounds which enable you to develop in 1.6 and up and still support devices on 1.5, but it's a pain. I am sure many developers will agree with this. Apart from this, there aren't major differences that would hinder developers in making apps to suit all platforms.
And with Android 3.0(Gingerbread), rumors say that it will bring support for tablet sized devices, I am not sure how to absorb this piece of news.
Saturday, July 17, 2010
Ongoing notifications in Android
I have blogged about is here. There's also a link to the source there which you can directly run.
Sunday, June 27, 2010
India get's Android 2.1 upgrade for HTC Hero
But, it seems that this is a two step upgrade process. The first one is the:
"Firmware over-the-air (FOTA) client update & YouTube player Update."
"Android 2.1 Platform Upgrade "
Thursday, June 17, 2010
Parcelable - How to do that in Android
Passing data between activities is quite easy. You would normally do that using the Bundle packed into an intent. But sometimes you need to pass complex objects from one activity to another. One workaround would be to keep a static instance of the object int your Activity and access it from you new Activity. This might help, but it's definitely not a good way to do this. To pass such objects directly through the Bundle, your class would need to implement the Parcelable interface.
For example you have a class called Student, which has three fields.
1. id
2. name
3. grade
You can create a POJO class for this, but you need to add some extra code to make it Parcelable. Have a look at the implementation.
1: public class Student implements Parcelable{
2: private String id;
3: private String name;
4: private String grade;
5:
6: // Constructor
7: public Student(String id, String name, String grade){
8: this.id = id;
9: this.name = name;
10: this.grade = grade;
11: }
12: // Getter and setter methods
13: .........
14: .........
15:
16: // Parcelling part
17: public Student(Parcel in){
18: String[] data = new String[3];
19:
20: in.readStringArray(data);
21: this.id = data[0];
22: this.name = data[1];
23: this.grade = data[2];
24: }
25:
26: @override
27: public int describeContents(){
28: return 0;
29: }
30:
31: @Override
32: public void writeToParcel(Parcel dest, int flags) {
33: dest.writeStringArray(new String[] {this.id,
34: this.name,
35: this.grade});
36: }
37: public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
38: public Student createFromParcel(Parcel in) {
39: return new Student(in);
40: }
41:
42: public Student[] newArray(int size) {
43: return new Student[size];
44: }
45: };
46: }
Once you have created this class, you can easily pass objects of this class through the Intent like this, and recover this object in the target activity.
1: intent.putExtra("student", new Student("1","Mike","6"));
Here, the student is the key which you would require to unparcel the data from the bundle.
1: Bundle data = getIntent().getExtras();
2: Student student = data.getParcelable("student");
This example shows only String types. But, you can parcel any kind of data you want. Try it out.
Tuesday, June 8, 2010
TextView with HTML content with Images
Say, if you have a TextView tv, and there's some HTML string with bold and italicized text, bringing it up on the TextView is pretty simple.
One line code for that:
tv.setText(Html.fromHtml(source));
where the source is actually your HTML string. This works perfectly. But how do we show images if there are any. Well, it's a bit tricky. You have to use the other method that takes in an ImageGetter and a TagHandler.
fromHtml(String source, Html.ImageGetter imageGetter, Html.TagHandler tagHandler)
The tagHandler is for situations where you wish to handle specific tags differently. I didn't wish to do that, so I just passed null there.
Now comes the main task. How do you get the image on to the TextView!!!!
Implement the Html.ImageGetter's getDrawable method which handles downloading the image, or accessing it from the net, and then create a drawable and return that object.
static ImageGetter imgGetter = new Html.ImageGetter() {
@Override
public Drawable getDrawable(String source) {
Drawable drawable = null;
drawable = Drawable.createFromPath(source); // Or fetch it from the URL
// Important
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable
.getIntrinsicHeight());
return drawable;
}
};
and use the method on the TextView like this.
tv.setText(Html.fromHtml(source, imgGetter, null);
This will load the TextView with the image. But this call to the getDrawable method is not asynchronous. So, until and unless that method returns, you UI will be blocked. In my case, I am creating the drawable from a local image, so, it didn't take much time. But, if you want to fetch an image from the web, you have to make this call in a separate thread, so that the UI is not blocked.
So, check your HTML string if they contain any images that have to be downloaded. If you find any, create a thread that download that image, saves it somewhere and returns you the location of that file. Now, change the src tags to point to the local images, and call setText method on the TextView.
And that should do it. The important thing to remember is, you have to change the HTML to point it to the file that you have downloaded.
Sample Source code : http://code.google.com/p/myandroidwidgets/source/browse/#svn/trunk/TextViewHTML
This sample doesn't use threads. So, your UI will be blocked unitl the image here is downloaded. So, keep waiting. :)
Wednesday, June 2, 2010
Checking Network Availability
The code:
public static boolean isNetworkAvailable(Context context) {
boolean value = false;
ConnectivityManager manager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = manager.getActiveNetworkInfo();
if (info != null && info.isAvailable()) {
value = true;
}
return value;
}
Thursday, April 8, 2010
Simple Drag n Drop on Android
Theory: Go for a FrameLayout.
FrameLayout is designed to block out an area on the screen to display a single item. You can add multiple children to a FrameLayout, but all children are pegged to the top left of the screen. Children are drawn in a stack, with the most recently added child on top.
In our main layout, we have a single button. We write a touch listener which will track the touch events and also help us to move the button around the screen. In this example, we will not be moving the button, but it’s image which we set to a ImageView. Also, instead of actually moving the ImageView, we will change the padding of the ImageView as the mouse moves, which will give an impression of the ImageView being moved.
The source code for this can be found on this link.
Drag and Drop example
Monday, April 5, 2010
Custom ProgressBar for Android
1. MyProgressBar.java
This class extends the ProgressBar class and has two methods that we would need to call to start and stop the animation.
To start the animation: call startAnimation()
To stop the animation: call dismiss()
Basically, we run a thread which keeps on switching the images. That's it.
2. myprogressbar.xml
This is the layout that the MyProgressBar would be using. This animation would be using 9 images which are in the drawable folder.
You can check out the whole project from the SVN. Here is the link.
https://myandroidwidgets.googlecode.com/svn/trunk/Custom_Progress_Bar
Sunday, April 4, 2010
Custom AutoComplete for Android
So here we go.
1. Class CustomAutoComplete.java
1: package com.beanie.example.widgets;
2: import android.content.Context;
3: import android.text.TextUtils;
4: import android.util.AttributeSet;
5: import android.widget.AutoCompleteTextView;
6:
7: public class CustomAutoComplete extends AutoCompleteTextView {
8: private String previous = "";
9: private String seperator = ";";
10: public CustomAutoComplete(final Context context, final AttributeSet attrs, final int defStyle) {
11: super(context, attrs, defStyle);
12: this.setThreshold(0);
13: }
14: public CustomAutoComplete(final Context context, final AttributeSet attrs) {
15: super(context, attrs);
16: this.setThreshold(0);
17: }
18: public CustomAutoComplete(final Context context) {
19: super(context);
20: this.setThreshold(0);
21: }
22: /**
23: * This method filters out the existing text till the separator
24: * and launched the filtering process again
25: */
26: @Override
27: protected void performFiltering(final CharSequence text, final int keyCode) {
28: String filterText = text.toString().trim();
29: previous = filterText.substring(0,filterText.lastIndexOf(getSeperator())+1);
30: filterText = filterText.substring(filterText.lastIndexOf(getSeperator()) + 1);
31: if(!TextUtils.isEmpty(filterText)){
32: super.performFiltering(filterText, keyCode);
33: }
34: }
35: /**
36: * After a selection, capture the new value and append to the existing
37: * text
38: */
39: @Override
40: protected void replaceText(final CharSequence text) {
41: super.replaceText(previous+text+getSeperator());
42: }
43: public String getSeperator() {
44: return seperator;
45: }
46: public void setSeperator(final String seperator) {
47: this.seperator = seperator;
48: }
49: }
protected void replaceText(final CharSequence text)
protected void performFiltering(final CharSequence text, final int keyCode)2. You main layout file (main.xml)
1: <?xml version="1.0" encoding="utf-8"?>
2: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3: android:orientation="vertical" android:layout_width="fill_parent"
4: android:layout_height="fill_parent">
5: <com.beanie.example.widgets.CustomAutoComplete android:layout_width="fill_parent"
6: android:layout_height="wrap_content" android:id="@+id/autocomplete"/>
7: </LinearLayout>
1: package com.beanie.example;
2: import android.app.Activity;
3: import android.os.Bundle;
4: import android.widget.ArrayAdapter;
5: import com.beanie.example.widgets.CustomAutoComplete;
6:
7: public class TestAutoComplete extends Activity {
8: /** Called when the activity is first created. */
9: @Override
10: public void onCreate(Bundle savedInstanceState) {
11: super.onCreate(savedInstanceState);
12: setContentView(R.layout.main);
13: CustomAutoComplete myAutoComplete = (CustomAutoComplete)findViewById(R.id.autocomplete);
14: ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line);
15:
16: adapter.add("aaaa");
17: adapter.add("abaa");
18: adapter.add("acaa");
19: adapter.add("adaa");
20: adapter.add("aaba");
21: adapter.add("aaca");
22: adapter.add("aaba");
23: adapter.add("aaae");
24:
25: myAutoComplete.setAdapter(adapter);
26: }
27: }
You can also change the separator from the default “;” to any other character like a “,” or anything else.
On the adapter, you call the method setSeparator(String any);
Now you have your own custom auto-complete widget for Android.
For this particular example, however, Android provides you a widget by default. MultiAutoCompleteTextView is specifically designed to handle such kind of input.