tag:blogger.com,1999:blog-40229029634533997042024-03-13T23:02:11.684-07:00My small world of AndroidThis blog is to share some of my thoughts and understanding of Android <a href="http://www.javacodegeeks.com/"><img alt="Java Code Geeks" src="http://4.bp.blogspot.com/_tWwHCKnIbjs/TPIBwpd71cI/AAAAAAAAAEw/3zbNwgbGYDM/s1600/logo_jcg_115x100.png" title="Java Code Geeks"></a>Ashimita Adusumillihttp://www.blogger.com/profile/06162890647943651215noreply@blogger.comBlogger10125tag:blogger.com,1999:blog-4022902963453399704.post-50484918971813121502012-04-09T23:10:00.000-07:002012-04-09T23:10:18.546-07:00Broadcast receiver - a change in flow since API 3.1<div dir="ltr" style="text-align: left;" trbidi="on">
Prior to API 3.1 we could have a broadcast receiver which could have been invoked by an implicit intent even if the application to which it belonged was in stopped state.<br />
<div>
<br /></div>
But this posed a security threat. Hence Google made it mandatory that for any broadcast receiver to receive an intent, there should be an activity and the application should not be in stopped state. Here is the <a href="http://developer.android.com/sdk/android-3.1.html">link </a>for further reading.<br />
<div>
<br /></div>
<div>
When an application is launched, it is in stopped state and hence it mandates the user to activate the application which has the broadcast receiver. If the application is force stopped by the user, then again the broadcast receiver fails to receive the intent. Hence apk having only broadcast receiver and developed on version prior to 3.1 will no longer work for later versions. </div>
<div>
<br /></div>
<div>
However one can make use of <b><span style="color: blue;">FLAG_INCLUDE_STOPPED_PACKAGES</span></b> to activate components in stopped application. This will not require creation of another activity in order to use the broadcast receiver. </div>
<div style="text-align: center;">
<i>Intent intent = new Intent("com.custom.intent");
<b>intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);</b> </i></div>
<div style="text-align: center;">
<i>this.sendBroadcast(intent);</i></div>
<div>
<br /></div>
<div>
The other way as I had mentioned earlier would be to write an activity which may or may not be a launcher activity. </div>
<div style="text-align: center;">
<i>PackageManager pm = getPackageManager(); </i></div>
<div style="text-align: center;">
<i>Intent appStartIntent = </i></div>
<div style="text-align: center;">
<i>pm.getLaunchIntentForPackage("com.your.broadcast.receiver.package");</i></div>
<div style="text-align: center;">
<i>if (null != appStartIntent)</i></div>
<div style="text-align: center;">
<i>{ </i></div>
<div style="text-align: center;">
<i> startActivity(appStartIntent);</i></div>
<div style="text-align: center;">
<i> }</i></div>
<div>
<br /></div>
<div>
If it is not a launcher app, then you need to mention the the category as<span style="color: blue;"> <b>INFO</b></span> in the intent-filter in the manifest file of the broadcast receiver. </div>
<div>
<category android:name="android.intent.category.INFO">This is a sample manifest file:</category><br />
<category android:name="android.intent.category.INFO"></category><br />
<blockquote class="tr_bq" style="text-align: left;">
<span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small;"><</span><i><span style="color: #741b47;">application</span></i></blockquote>
<blockquote class="tr_bq">
<div style="text-align: left;">
<i><span style="color: #741b47;"> android:icon="@drawable/ic_launcher"</span></i></div>
<i><div style="text-align: left;">
<i><span style="color: #741b47;"> android:label="@string/app_name" </span></i></div>
<div style="text-align: left;">
<i><span style="color: #741b47;"> android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" </span><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small;">></span></i></div>
</i><i><div style="text-align: left;">
<i><span style="color: #741b47;"> </span></i><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small; text-align: -webkit-auto;"><</span><i><span style="color: #741b47;">activity</span></i></div>
</i></blockquote>
<blockquote class="tr_bq">
<div style="text-align: left;">
<i><span style="color: #741b47;"> android:name=".InvokedActivity"</span></i></div>
<i><div style="text-align: left;">
<i><span style="color: #741b47;"> android:label="@string/app_name"</span></i><i><div style="display: inline !important; text-align: -webkit-auto;">
<i><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small;">></span></i></div>
</i></div>
</i></blockquote>
<blockquote class="tr_bq">
<div style="text-align: left;">
<i><span style="color: #741b47;"> </span></i><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small; text-align: -webkit-auto;"><</span><i><span style="color: #741b47;">intent-filter</span></i><i><div style="display: inline !important; text-align: -webkit-auto;">
<i><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small;">></span></i></div>
</i></div>
<i><div style="text-align: left;">
<i><span style="color: #741b47;"> </span></i><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small; text-align: -webkit-auto;"><</span><i><span style="color: #741b47;">action android:name="android.intent.action.MAIN" /</span></i><i><div style="display: inline !important; text-align: -webkit-auto;">
<i><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small;">></span></i></div>
</i> </div>
</i></blockquote>
<blockquote class="tr_bq" style="text-align: left;">
<i><span style="color: #741b47;"> </span></i><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small; text-align: -webkit-auto;"><</span><i><b><span style="color: #4c1130;">category android:name="android.intent.category.INFO"</span></b><span style="color: #741b47;"> /</span></i><i style="text-align: left;"><div style="display: inline !important; text-align: center;">
<i><span style="color: #741b47;"> </span><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small;">></span></i></div>
</i></blockquote>
<div style="text-align: center;">
<span style="color: #c27ba0;"><span style="font-family: Arial, Verdana, Arial, 'sans serif'; text-align: -webkit-auto;"><-- <i>If the activity is a launcher then mention this instead</i></span><i> </i></span></div>
<div style="text-align: center;">
<span style="color: #c27ba0;"> <i> </i><span style="font-family: Arial, Verdana, Arial, 'sans serif'; text-align: -webkit-auto;"><</span><i><b>category android:name="android.intent.category.LAUNCHER"</b> /</i><i></i></span></div>
<span style="color: #c27ba0;"><div style="display: inline !important; text-align: center;">
<i><i> <span style="font-family: Arial, Verdana, Arial, 'sans serif';">></span></i></i></div>
--<i><div style="display: inline !important; text-align: center;">
<i><span style="font-family: Arial, Verdana, Arial, 'sans serif';">></span></i></div>
</i></span><br />
<blockquote class="tr_bq">
<div style="text-align: left;">
<i><span style="color: #741b47;"> </span></i><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small; text-align: -webkit-auto;"><</span><i><span style="color: #741b47;">/intent-filter</span></i><i style="text-align: left;"><div style="display: inline !important; text-align: center;">
<i><span style="color: #741b47;"> </span><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small;">></span></i></div>
</i></div>
<i><div style="text-align: left;">
<i><span style="color: #741b47;"> </span></i><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small; text-align: -webkit-auto;"><</span><i><span style="color: #741b47;">/activity</span></i><i style="text-align: left;"><div style="display: inline !important; text-align: center;">
<i><span style="color: #741b47;"> </span><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small;">></span></i></div>
</i></div>
</i><i><div style="text-align: left;">
<i><span style="color: #741b47;"> </span></i><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small; text-align: -webkit-auto;"><</span><i><span style="color: #741b47;">receiver android:name=".TestBroadCastReceiver"</span></i><i style="text-align: left;"><div style="display: inline !important; text-align: center;">
<i><span style="color: #741b47;"> </span><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small;">></span></i></div>
</i></div>
</i><i><div style="text-align: left;">
<i><span style="color: #741b47;"> </span></i><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small; text-align: -webkit-auto;"><</span><i><span style="color: #741b47;">intent-filter</span></i><i style="text-align: left;"><div style="display: inline !important; text-align: center;">
<i><span style="color: #741b47;"> </span><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small;">></span></i></div>
</i></div>
</i><i><div style="text-align: left;">
<i><span style="color: #741b47;"> </span></i><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small; text-align: -webkit-auto;"><</span><i><span style="color: #741b47;">action android:name="</span></i><i style="text-align: center;">com.custom.intent</i><i><span style="color: #741b47;">"</span></i><i style="text-align: left;"><div style="display: inline !important; text-align: center;">
<i><span style="color: #741b47;"> </span><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small;">></span></i></div>
</i></div>
</i><i><div style="text-align: left;">
<i><span style="color: #741b47;"> </span></i><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small; text-align: -webkit-auto;"><</span><i><span style="color: #741b47;">/action</span></i><i style="text-align: left;"><div style="display: inline !important; text-align: center;">
<i><span style="color: #741b47;"> </span><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small;">></span></i></div>
</i></div>
</i><i><div style="text-align: left;">
<i><span style="color: #741b47;"> </span></i><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small; text-align: -webkit-auto;"><</span><i><span style="color: #741b47;">/intent-filter</span></i><i style="text-align: left;"><div style="display: inline !important; text-align: center;">
<i><span style="color: #741b47;"> </span><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small;">></span></i></div>
</i></div>
</i><i><div style="text-align: left;">
<i><span style="color: #741b47;"> </span></i><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small; text-align: -webkit-auto;"><</span><i><span style="color: #741b47;">/receiver</span></i><i style="text-align: left;"><div style="display: inline !important; text-align: center;">
<i><span style="color: #741b47;"> </span><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small;">></span></i></div>
</i></div>
</i><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small; text-align: -webkit-auto;"><div style="text-align: left;">
<span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small;"><</span><i style="font-family: 'Times New Roman'; font-size: medium;"><span style="color: #741b47;">application</span></i><i style="text-align: left;"><div style="display: inline !important; text-align: center;">
<i><span style="color: #741b47;"> </span><span style="font-family: Arial, Verdana, Arial, 'sans serif'; font-size: x-small;">></span></i></div>
</i></div>
</span></blockquote>
<i><span style="color: #741b47;"> </span></i><br />
</div>
<div>
<div style="text-align: left;">
<category android:name="android.intent.category.INFO"> </category></div>
</div>
<div>
<category android:name="android.intent.category.INFO"><i><manifest android:versioncode="1" android:versionname="1.0" package="com.check.receiver" xmlns:android="http://schemas.android.com/apk/res/android"><uses-sdk android:minsdkversion="12"><application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"><activity android:label="@string/app_name" android:name=".InvokedActivity"><intent-filter><action android:name="android.intent.action.MAIN"><b><category android:name="android.intent.category.INFO"></category></b></action></intent-filter></activity><receiver android:name=".TestBroadCastReceiver"><intent-filter><action android:name="com.custom.intent"></action></intent-filter></receiver></application></uses-sdk></manifest></i>Here is the code for BroadCastReceiver:</category></div>
<div>
<category android:name="android.intent.category.INFO"><br /></category></div>
<div style="text-align: center;">
<category android:name="android.intent.category.INFO"><i>public class TestBroadCastReceiver extends BroadcastReceiver </i></category><i>{ </i></div>
<div style="text-align: center;">
<i> private static final String CUSTOM_INTENT = "com.custom.intent";</i></div>
<div style="text-align: center;">
<i> public void onReceive(Context context, Intent intent) {</i></div>
<div style="text-align: center;">
<i> if (intent.getAction().equals(CUSTOM_INTENT)) {</i></div>
<div style="text-align: center;">
<i> //your code here
} </i></div>
<div style="text-align: center;">
<i> }</i></div>
<div style="text-align: center;">
<i> }</i> </div>
<div>
<br /></div>
<div>
The code for InvokedActivity:</div>
<div>
<br /></div>
<div style="text-align: center;">
<i>public class InvokedActivity extends Activity { </i></div>
<div style="text-align: center;">
<i> public void onCreate(Bundle b) { </i></div>
<div style="text-align: center;">
<i> super.onCreate(b); </i></div>
<div style="text-align: center;">
<i> /*Toast.makeText(this, "starting xyz receiver...blah blah :)", Toast.LENGTH_LONG)
.show();*/
finish();</i></div>
<div style="text-align: center;">
<i> } </i></div>
<div style="text-align: center;">
<i>}</i></div>
<div>
</div>
</div>
Ashimita Adusumillihttp://www.blogger.com/profile/06162890647943651215noreply@blogger.com6tag:blogger.com,1999:blog-4022902963453399704.post-54244891713608550932011-12-08T21:12:00.001-08:002012-04-02T21:39:53.966-07:00Read out SMS using Text to speech APIOne day my colleague wanted me to write a small SMS app for her. The app would read out loudly the name of the sender and also the contents of the SMS. Well, she later changed her mind and said, "No, please don't read out the contents. Just the name of the sender would do". It was fun coding the app. There are so many Android apps available in the market which does the same thing. To tell you the truth, I was first happy to see my Google Nexus reading out the contents but hearing the audio every time the SMS arrives is little annoying. So I have conveniently decreased the media volume so that it doesn't bother me with all the junk SMS that I get all day. :)
<p>Btw, I still have the content being read out. You may want to comment it out, if it infringes on your privacy. :D.
<p>This app does not have an activity. Not required, anyway, isn't it? <p>There is <b>TextToSpeechService</b> which runs in the background and a <b>SMSReceiver</b> which extends Broadcast receiver. SMSReceiver, on receiving an intent of <i>"android.provider.Telephony.SMS_RECEIVED"</i> , triggers the TextToSpeechService which does all the talking. This is pretty much the summary.
<p>You will see some hardcoding in the speakWords(...) method,
E.g. StringBuffer buf = new StringBuffer("You have sms from....");
<p>You may put all the hard-coding in the strings.xml. This is just a simple example. The app can be extended to look up the phone book and read out the sms only if the sender is in the contacts list.
<p>I can mail you the source code if would like to play around. :)Ashimita Adusumillihttp://www.blogger.com/profile/06162890647943651215noreply@blogger.com3tag:blogger.com,1999:blog-4022902963453399704.post-20445819888019031302011-11-24T21:25:00.000-08:002011-11-24T21:25:47.149-08:00"I can be called only once please" says ...onCreateDialog()As the title says, I learnt the lesson hard way. I had a code like this:<br />
<br />
onCreateDialog(int id, Bundle args) {<br />
switch (id) {<br />
case DELETE_DIALOG: {<br />
final AlertDialog.Builder builder = new Builder(this);<br />
builder.setTitle(R.string.confirm_delete_title)<br />
.setMessage(R.string.confirm_delete_message)<br />
.setPositiveButton(R.string.btn_ok, mFileDialogListener)<br />
.setNegativeButton(R.string.btn_cancel, mFileDialogListener);<br />
<b>//initializeProgressMessageDependingOnId(id);</b><br />
return builder.create();<br />
// other cases....<br />
}<br />
Now, I was expecting every time a dialog Box is created my <b>initializeProgressMessageDependingOnId()</b> would be called. This would initialize the message that needs to be shown while "DELETE_DIALOG" case is executing in the background. But to my surprise I found that that it does not happen that way. While the first time it invokes the initializeProgressMessage...() method with the "id" (say DELETE_DIALOG) the subsequent calls do not result in invoking the method with different "id". Later I found that once the activiy is created and onCreateDialog is invoked, it stores the information of which dialog box to instantiate for each id. It "does not" invoke the onCreateDialog repeatedly. So once initializeProgressMessageDependingOnId(id) was invoked for the first time, it was never again executed. I rectified it by putting the required method calls inside the "mFileDialogListener" code associated with the dialog box.<br />
<br />
private final DialogInterface.OnClickListener mFileDialogListener = new DialogInterface.OnClickListener() {<br />
@Override<br />
public void onClick(DialogInterface dialog, int which) {<br />
switch (which) {<br />
case DialogInterface.BUTTON_POSITIVE:<br />
handleButtonClick(mCurrentAction);<br />
<b>//handleButtonClick would in turn do the needful</b><br />
break;<br />
case DialogInterface.BUTTON_NEGATIVE:<br />
dialog.cancel();<br />
}<br />
}<br />
};<br />
};Ashimita Adusumillihttp://www.blogger.com/profile/06162890647943651215noreply@blogger.com0tag:blogger.com,1999:blog-4022902963453399704.post-42703117004152658142011-06-10T07:35:00.000-07:002011-06-17T04:54:28.607-07:00How Android prevents Google Transport Spoof<div dir="ltr" style="text-align: left;" trbidi="on">Few days back, I was reading a <a href="http://latimesblogs.latimes.com/technology/2011/05/google-fixing-android-flaw-that-could-have-leaked-personal-data-from-millions-of-phones.html">blog</a> which says that Google has managed to tighten it's security to prevent apps from siphoning personal data of the users from an Android device. Now that is interesting!<br />
In the Gingerbread sdk, if one looks at the <i style="background-color: #f3f3f3; color: #274e13;">BackupManagerService.java</i>, one can see a very interesting piece of code with explanatory comments.<br />
<br />
try {<br />
<span style="color: #274e13;"> </span><i style="color: #274e13;">// If there's something out there that is supposed to be the Google<br />
// backup transport, make sure it's legitimately part of the OS build<br />
// and not an app lying about its package name.</i><br />
ApplicationInfo info = mPackageManager.<wbr></wbr>getApplicationInfo(<br />
transportComponent.<wbr></wbr>getPackageName(), 0); <br />
if ((<i style="background-color: #f3f3f3;"><span style="color: #274e13;">info.flags & ApplicationInfo.FLAG_SYSTEM) != 0</span></i>) {<br />
if (DEBUG) Slog.v(TAG, "Binding to Google transport");<br />
Intent intent = new Intent().setComponent(<wbr></wbr>transportComponent);<br />
<i style="background-color: #f3f3f3;">context.bindService(intent, mGoogleConnection, Context.BIND_AUTO_CREATE);</i><br />
} else {<br />
<span style="background-color: #f3f3f3;"> <span style="color: #38761d;">Slog.w(TAG, "Possible Google transport spoof: ignoring " + info);</span></span><br />
}<br />
} catch (PackageManager.<wbr></wbr>NameNotFoundException nnf) {<br />
// No such package? No binding.<br />
if (DEBUG) Slog.v(TAG, "Google transport not present");<br />
} <br />
<br />
I guess this wasn't there prior to Gingerbread, but I am not sure, if the blog talks about some other security.<br />
What I understand is that, without this check any app could have actually tricked the BackupManagerService to bind to itself to get the data that the user is trying to backup, assuming this service was enabled.</div>Ashimita Adusumillihttp://www.blogger.com/profile/06162890647943651215noreply@blogger.com0tag:blogger.com,1999:blog-4022902963453399704.post-60128367245649535632011-06-10T07:12:00.000-07:002011-06-10T07:44:30.023-07:00Using Simple API to marshal and unmarshal xml<div dir="ltr" style="text-align: left;" trbidi="on">I had been using Simple Api for quite some time now to marshal and UN-marshal xml files to Java classes on Android. While I tried my hand with XPP, Spring Android but I found Simple to be absolutely simple!! It works like a charm. Interestingly, Spring also uses Simple Api. It has support for posts like atom, rss feeds. But all these can be done using only Simple as well. Here is the <a href="http://simple.sourceforge.net/">link</a> for Simple. The code examples are easy to follow. All one needs to do is to put the jar into Android (or any java project) project's classpath.<br />
In addition to all the serialization/de-serialization magic that it performs,one thing that I like about Simple is the ability to write the data from the class into an OutputStream. For e.g:<br />
<br />
<div style="background-color: #f3f3f3;"><i style="background-color: #f3f3f3; color: #274e13;">/</i><i style="color: #274e13;">/MyXml is the class </i></div><div style="background-color: #f3f3f3; color: #274e13;"><i> MyXml myXml = new MyXml();</i></div><div style="background-color: #f3f3f3; color: #274e13;"><i> myXml.description = "some_desc";</i></div><div style="background-color: #f3f3f3; color: #274e13;"><i> myXml.name = "some_name";</i></div><div style="background-color: #f3f3f3; color: #274e13;"><i>//assuming MyXml has already been defined the way the xml is going to be parsed, //with it's root, elements, attributes.</i></div><div style="background-color: #f3f3f3;"><br />
</div><div style="background-color: #f3f3f3; color: #274e13;"><i>Serializer serializer = new Persister();</i></div><div style="background-color: #f3f3f3; color: #274e13;"><i>ByteArrayOutputStream bos = new ByteArrayOutputStream();</i></div><div style="background-color: #f3f3f3; color: #274e13;"><i>try { </i></div><div style="background-color: #f3f3f3; color: #274e13;"><i>serializer.write(myXml, bos);</i></div><div style="background-color: #f3f3f3; color: #274e13;"><i>}catch(Exception e) {//whatever}</i></div><br />
I do not appreciate putting a try/catch block with a generic "Exception" but that is how the api is written. It mandates you to catch a generic Exception. Hope they will modify that later.<br />
<br />
It can be used to generate the xml in the form of a String:<br />
<div style="background-color: #f3f3f3; color: #274e13;"><i>String xmlString = new String(bos.toByteArray(), "UTF-8");</i></div>This String can be sent as a data to some server over Http from Android, if the need be.<br />
One can also write the contents to a file instead of a OutputStream.<br />
<div style="background-color: #f3f3f3; color: #274e13;"><i>File file = new File(Environment.getExternalStorageDirectory()</i></div><div style="background-color: #f3f3f3; color: #274e13;"><i> + "/some.xml");</i></div><div style="background-color: #f3f3f3; color: #274e13;"><i>serializer.write(myXml, file);</i></div>Again that should be inside a try/catch...ah what an innovative way to catch Exception... pun intended!!<br />
But I just love Simple...somebody had once said, "Simple living and high thinking"....I can attribute this to Simple api..."Simple parsing and high performing"!<br />
<br />
</div>Ashimita Adusumillihttp://www.blogger.com/profile/06162890647943651215noreply@blogger.com2tag:blogger.com,1999:blog-4022902963453399704.post-82016046990486806332011-05-10T02:45:00.000-07:002012-05-30T22:40:03.416-07:00Using JackRabbit as a WebDAV client for Android<div dir="ltr" style="text-align: left;" trbidi="on">
I have been looking for a WebDAV client to work on Android. Some of the WebDAV clients that are available are Jakarata Slide (which is now retired), JackRabbit (Apache open source) and Sardine (from Google code). I zeroed in on JackRabbit2.2.5 as Sardine was not working and did not want to spend time on debugging. But then JackRabbit did not work as well on Android. My first mistake was to download the jackrabbit-standalone.jar from the net, and trying to make it work. This was a 30+ MB file and hence not suitable for Android platform. Then I tried debugging the jackrabbit-webdav code. It internally uses some of the packages which Android does not support. After making all the "Android-happy" changes in the code, I built the jackrabbit-webdav-2.2.5.jar again using their pom.xml(maven). The files size was around 288 KB. I believe this can be optimized further, even though I did not spend much time in doing so later. :)<br />
Here is a code snippet to upload a file to the WebDAV server using the jar:<br />
<br />
<div style="text-align: left;">
<i><span style="color: blue;"> File file = new File(filePath);</span></i></div>
<div style="text-align: left;">
<i><span style="color: blue;"><span style="color: #666666;">/*PutMethod is a class in the jackrabbit-webdav for uploading files in the server*/</span></span></i><i><span style="color: blue;"> </span><br style="color: blue;" /><span style="color: blue;"> PutMethod putMethod = new PutMethod(baseURI+ uploadPath+file.getName()); <span style="color: #666666;"></span></span><br style="color: blue;" /><span style="color: blue;"> </span></i></div>
<div style="text-align: left;">
<i><span style="color: blue;">RequestEntity requestEntity = new InputStreamRequestEntity(new FileInputStream(file));</span><br style="color: blue;" /><span style="color: blue;"> </span></i></div>
<div style="text-align: left;">
<i><span style="color: blue;">putMethod.setRequestEntity(requestEntity);</span></i></div>
<div style="text-align: left;">
<i><span style="color: blue;"><span style="color: #666666;">//HttpClient httpClient</span></span></i><i><span style="color: blue;"> </span><span style="color: blue;"></span><span style="color: blue;"> </span></i></div>
<div style="text-align: left;">
<i><span style="color: blue;">httpClient.executeMethod(putMethod);</span></i></div>
<div style="text-align: left;">
<br /></div>
<span style="background-color: white;"><span style="color: black;">Same way, the <i style="color: blue;"><span style="color: #45818e;">MoveMethod, CopyMethod, DeleteMethod, MkColMethod (create), PropFindMethod</span> </i>(list the directory contents) can be used.</span></span><br />
<div>
<div style="color: #cc0000;">
<div style="background-color: white;">
<span style="background-color: white;">You can <a href="https://docs.google.com/open?id=0B_8d9MyfLLrZZjM2NzQ1YmQtODEwYy00MDc1LTkxNTctOWRiMDA2YTQ0NGVh" rel="nofollow" target="_blank">download</a> the jar file ! :).</span></div>
</div>
<br />
<br />
Edited:<br />
<span class="Apple-style-span" style="color: blue;">The above file do not contain the org.apache.commons.httpclient. You may want to dowload the same from the apache site and add to your project class path OR .....</span><br />
<br />
<br />
As one of the readers had requested to provide a jar file which includes the "org.apache.commons.httpclient", I have rebuilt my library to accommodate this change. This library is heavier than the previous one.<br />
<br />
<br />
Previously the commons-httpclient version 3.0 was used in my jackrabbit jar. As one of the readers of this post has pointed out, FileRequestEntity (for content chunking) was not being supported, I rebuilt my jar to include the same. This includes commons-httpclient version 3.1.<br />
<br />
So those of you who would like to use FileRequestEntity API for larger file upload, you can download the latest version of my jar. Here you go: <a href="https://docs.google.com/open?id=0B_8d9MyfLLrZellkSUVhSHdQcU0" rel="nofollow" target="_blank">jackrabbit-webdav-2.2.6-jar-with-dependencies.jar</a> (size: 919 KB)<br />
<br />
The older version (without FileRequestEntity) i.e. 2.2.5-jar, support only InputStreamRequestEntity and <b>not</b> FileRequestEntity. So those of you who would upload file of smaller size around 2 KB, can use the older version of my library: <a href="https://docs.google.com/open?id=0B_8d9MyfLLrZY2VkMjg3MmEtZDAzOS00YzY0LThmYTktMGMwNDBkZDc1MmEy" rel="nofollow" target="_blank">jackrabbit-webdav-2.2.5-jar-with-dependencies</a> (size 892 KB).</div>
<br />
I would appreciate your feedback or acknowledgement in the form of comments or a<b> g+</b> rating if my library has helped you. Thanks. :)</div>Ashimita Adusumillihttp://www.blogger.com/profile/06162890647943651215noreply@blogger.com54tag:blogger.com,1999:blog-4022902963453399704.post-24228111547330482432011-05-02T04:41:00.000-07:002011-05-02T04:41:39.998-07:00Using Java File Handler API vs Android File handler API<div dir="ltr" style="text-align: left;" trbidi="on">I had an application App1 whose package name was "com.sample".<br />
<br />
I decided to create a directory called "testdirectory" under "data/data/com.sample" so that it's path would be "<b>data/data/com.sample/testdirectory</b>".<br />
<br />
So, I wrote a code like this:<br />
<br />
File dir = <b>getDir("</b><b>testdirectory"</b>, Context.MODE_WORLD_WRITEABLE<b>);</b><br />
<b><br />
</b><br />
But what I got was :<br />
data/data/com.sample/<span class="Apple-style-span" style="color: red;"><b>app_</b></span>testdirectory<br />
getDir() is Android API.<br />
<br />
So I decided to try out java File handler:<br />
<br />
File dir = new File(<b>"</b><b><span class="Apple-style-span" style="font-weight: normal;"><b>data/data/com.sample/testdirectory</b></span>"</b>).mkdir();<br />
<br />
This created "<b>data/data/com.sample/directory</b>" without prefixing with the word "app_".<br />
So while Android's getDir() always prepends the word to the "app_" to the directory name, Java file handlers allows to create a directory without prefixing anything !</div>Ashimita Adusumillihttp://www.blogger.com/profile/06162890647943651215noreply@blogger.com0tag:blogger.com,1999:blog-4022902963453399704.post-90044464602272971632011-05-02T04:22:00.000-07:002011-05-02T04:22:30.199-07:00Using SharedUserId in Android App<div dir="ltr" style="text-align: left;" trbidi="on">I had this requirement where App1 needs to access(read,write) the file system of App2. That does not seem very easy and surely there is no straight forward way to do this. I stumbled upon the concept of using SharedUserId that Android allows. Both the apps should have the same shared user Id in their manifest file. I must admit that this is not a very ideal solution. One needs to be extremely cautious. For e.g. if App1 did not use Shared Id at the time of launch, but decides to go for it at the time of upgrade, the new application might crash in the sense that it's data package might become inaccessible. Otherwise if it already had a shared Id but decides to go for a different one during upgrade, it will meet with the same fate.<div>So while opting for shared User Id, it should be taken in to consideration, that it will not allow any modification later and also it should be one time activity at the beginning. Once used, it tells you "Please leave me alone". :) </div><div>There is already a <a href="http://code.google.com/p/android/issues/detail?can=2&q=1227&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&id=1227">bug</a> raised for this, as I came to know from one of the LinkedIn members of Google Android forum.</div></div>Ashimita Adusumillihttp://www.blogger.com/profile/06162890647943651215noreply@blogger.com0tag:blogger.com,1999:blog-4022902963453399704.post-4655433110697306712011-05-02T03:01:00.000-07:002011-05-02T03:36:56.578-07:00Plugging in the DropBox API to android applicationDropBox, as we all know is an online storage and it provides file browsing, synchronization, backup and share. They have support for mobile App development.<div>Their SDK encapsulate, the RESTful calls that they make over HTTP to interact with DropBox service. I was expecting a good online documentation, which would have made the developer's work easier, but sadly enough there was none, at least at the time of writing this post. So, I downloaded their <a href="https://www.dropbox.com/developers/releases">sample</a> application in Java (there were Python and Ruby versions as well). What helped me in understanding the usage, was the JUnit Testcases in the client code that is available for download. The sample app is only instantiating the client API (the one that makes the RESTful calls) and listing the contents of a directory. But if one goes through the JUnit Test cases, one can clearly understand the usages of the API. </div><div>Another important thing that I would like to mention here is that, while the DropBox api gives all meta data related information of a directory (account name, available storage, directory children etc.), if one wants to perform copy,move,delete operations on the user file System on the DropBox, one must instantiate the DropBox client: </div><div>Dropboxclient mClient = new DropboxClient(Map configMap, Authenticator auth);</div><div>IMHO, this could have been avoided if the DropBox guys provided CRUD implementation in the DropboxAPI itself. </div><div>DropboxAPI mApi = new DropboxAPI();</div><div>The DropboxAPI class already instantiates Dropboxclient. But then why to force the developers to instantiate it again just to get access to the CRUD operations?</div><div>But I guess it is still in evolving stage, as they have admitted their code is well tested in Python, Java and Ruby...in that order. :) </div><div>All in all, a very useful API if one wants to integrate the DropBox service for their Android app.</div>Ashimita Adusumillihttp://www.blogger.com/profile/06162890647943651215noreply@blogger.com0tag:blogger.com,1999:blog-4022902963453399704.post-54463211442292974052010-03-25T23:11:00.000-07:002010-03-25T23:35:34.721-07:00JQuery to rescue for css issue on IEIt all started this way..... Business wanted a print page (popup in an iframe) on our site which was half baked and the status quo remained the same for the last 6 months and the developer who coded it was no longer in the organization. The issue was mainly with the UI. Not having a UI background, I thought why not give it a shot!! I did resolve all the issues but the the header (having a logo) with other items on that should always remain on the viewport even when the users scrolls down the page. It works perfect with FF (all versions), chrome (still not regarded as a standard) . But then IE was a big disappointment. Very high z-index don't help and IE does not recognize "position:fixed". While there might be a lot of better solutions to this problem, but the one that really worked for me is <div>if(navigator.appName == "Microsoft Internet Explorer") {<div><span class="Apple-tab-span" style="white-space:pre"> </span>$jq(document).ready(function() {</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>$jq("#print_header_container").css("position", "absolute");//set other css attributes</div><div>}</div><div><div>$jq(window).scroll(function() {</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>$jq("#print_header_container").css("top", $jq(window).scrollTop() + "px");</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>$jq("#print_header_container").css("margin", "0 0 0 0px");</div><div><span class="Apple-tab-span" style="white-space:pre"> </span></div><div><span class="Apple-tab-span" style="white-space:pre"> </span>});</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>}<span class="Apple-tab-span" style="white-space:pre"> </span></div><div><span class="Apple-tab-span" style="white-space:pre">B</span>ut then there is still a flicker as the user scrolls but it is negligible...phew! :)</div></div></div>Ashimita Adusumillihttp://www.blogger.com/profile/06162890647943651215noreply@blogger.com0