Best android questions in April 2012

When NOT to call super() method when overriding?

44 votes

When I make my own Android custom class, I extend its native class. Then when I want to override the base method, I always call super() method, just like I always do in onCreate, onStop, etc.

And I thought this is it, as from the very beginning Android team advised us to always call super on every method override.

But, in many books I can see that developers, more experienced than myself, often omit calling super and I really doubt they do it as a lack of knowledge. For example, look at this basic SAX parser class where super is omitted in startElement, characters and endElement:

public class SAXParser extends DefaultHandler{
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        if(qName.equalsIgnoreCase("XXY")) {
            //do something
        }
    }

    public void characters(char[] ch, int start, int length) throws SAXException {
        //do something
    }

    public void endElement(String uri, String localName, String qName) throws SAXException {
        if(qName.equalsIgnoreCase("XXY")) {
            //do something
        }else () {
            //do something
        }
    }
}

If you try to create any override method via Eclipse or any other IDE, super will always be created as a part of automated process.

This was just a simple example. Books are full of similar code.

How do they know when you must call super and when you can omit it calling?

PS. Do not bind to this specific example. It was just an example randomly picked from many examples.

(This may sound like a beginner question, but I am really confused.)

By calling the super method, you're not overriding the behavior of the method, you're extending it.

A call to super will perform any logic the class you're extending has defined for that method. Take into account that it might be important the moment when you call super's implementation in your method overriding. For instance:

public class A { 
    public void save() { 
         // Perform save logic
    }
}

public class B extends A {
    private Object b;
    @Override
    public void save() { 
        super.save(); // Performs the save logic for A
        save(b); // Perform additional save logic
    }
}

A call to B.save() will perform the save() logic for both A and B, in this particular order. If you weren't calling super.save() inside B.save(), A.save() wouldn't be called. And if you called super.save() after save(b), A.save() would be effectively performed afterwards B.save().

If you want to override super's behavior (that is, fully ignore its implementation and provide it all yourself), you shouldn't be calling super.

In the SAXParser example you provide, the implementations of DefaultHandler for those methods are just empty, so that subclasses can override them and provide a behavior for those methods. In the javadoc for this method this is also pointed out.

public void startElement (String uri, String localName,
    String qName, Attributes attributes) throws SAXException {
    // no op
}

About the super() default call in code generated by IDEs, as @barsju pointed out in his comment, in each constructor there's an implicit call to super() (even if you don't write it in your code), which means, in that context, a call to super's default constructor. The IDE just writes it down for you, but it would also get called if you removed it. Also notice that when implementing constructors, super() or any of its variants with arguments (i.e. super(x,y,z)) can only be called at the very beginning of the method.

Override Power button just like Home button

13 votes

Well, i am Doing a stuff in which I want to disable all hard button of the device

Hard button like Power, Home, Volume up, Volume down, Search, Back.

I successfully override almost all buttons Here except Power

so i just want you people to see and please share some idea so that I can away with it

I am getting the long press Power keyevent in onDispatchKeyEvent(), sameway i wanted to catch short click of the same. Morever when pressing power i also tried to stop Screen off by getting the Broadcast of SCREEN_OFF and succeed to receive but not able to handle it.

Thanks.

Till i had created a RecieverScreen which recieves broadcast of Screen on/off

ReceiverScreen.java

public class ReceiverScreen extends BroadcastReceiver {

    public static boolean wasScreenOn = true;

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
            // do whatever you need to do here
            wasScreenOn = false;
        } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
            // and do whatever you need to do here
            wasScreenOn = true;
        }
    }
}

DisableHardButton.java

public class DisableHardButton extends Activity {

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

    setContentView(R.layout.main);
    IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
    filter.addAction(Intent.ACTION_SCREEN_OFF);
    BroadcastReceiver mReceiver = new ReceiverScreen();
    registerReceiver(mReceiver, filter);
    }

@Override
    protected void onPause() {
        // when the screen is about to turn off
        if (ScreenReceiver.wasScreenOn) {
            // this is the case when onPause() is called by the system due to a screen state change
            System.out.println("SCREEN TURNED OFF");

    } else {
        // this is when onPause() is called when the screen state has not changed
    }
    super.onPause();
}

@Override
protected void onResume() {
    // only when screen turns on
    if (!ScreenReceiver.wasScreenOn) {
        // this is when onResume() is called due to a screen state change
        System.out.println("SCREEN TURNED ON");
    } else {
        // this is when onResume() is called when the screen state has not changed
    }
    super.onResume();
}
}

Phew. This is quite a contended question, with a great deal of commentary behind it.

Let me begin by rephrasing your question a bit. If I understand clearly, you'd like to disable all physical buttons on the device for the duration of your activity. This is inclusive of the power button, which you detect by handling the ACTION_SCREEN_OFF intent. Your current (successful) workaround for this scenario is to broadcast an ACTION_SCREEN_ON, kicking the screen back to life when it's turned off, provided the host implements this correctly.

You'd now like to go the extra mile, by rendering this action unnecessary, if (and only if) you are able to catch and handle ACTION_SCREEN_OFF before it gets sent to the system. Is this possible, and if so, how?

This bears some discussion. The short version, however, is simple: this is not possible, without custom modification to your firmware or the core of the Android operating system, for a limited number of devices.

The Android system, as far as is documented, defines this as a broadcast action. Following the publish-subscribe pattern of message propagation, this message will notify all concerned parties of this action. Because this message is sent by the system, because the message stack is managed by the system, and because the message is also received by the system, your code simply isn't injected in the right place to block the reception of this message.

Furthermore, for some devices, this will be a physical switch that has no programmatic interrupt whatsoever. At best, the Android system can hope to handle for the event when it happens, which is precisely why this broadcast message is something of a special case in the service stack. To the best of my knowledge and based upon the sparse documentation on this scenario, this is why it's not an out-of-the-box, supported feature, before we consider any of the possible vectors for abuse.

Your best recourse is actually a much simpler one, if you have the ability to modify the physical hardware for the device in question: restrict access to, mangle, or otherwise disable the physical power button. In many scenarios this is undesirable, but this works in situations where your Android device is being used, for example, as a point-of-sale or a public service machine. If this is unworkable, placing physical restrictions on access to the power button may be all that's required, handling for the remainder of cases (for example, spot attempts to toggle the screen) by sending ACTION_SCREEN_ON.

Just remember, this strategy isn't foolproof. Do this competently and document the procedure well, lest you become fodder for the next 2600 exposé.

Best of luck with your application.

android nGPS: get location based on magnetic field instead of gps or cell triangulation

11 votes

Does anybody know how to convert results from the magnetic-field sensor from an android device to coordinates using the World Magnetic Model? Is there a webservice that does that?

You cannot do this. First of all you want co-ordinates which means 2 values. Only one what magnetic field provides is not enough. Second - even if you catch it correctly you will only know that you are on one of those isolines. That's not too much. You can be in Europe or Africa as well. Third and final - it's real magnetic field around you. Nearby passing car which is heavy metallic object object will change your field dramatically. Other magnetic sources like your phone ringing or electric wiring around will tell you that you travel from Brasil to Egypt when you come form Bathroom to Living room.

Use system PIN dialog in Android application

11 votes

Background

I am trying to write an application which works like described below.

  • When user start application it check if user have registered PIN on his device.
  • If user have registered PIN, application must show button "Continue with PIN".
  • When user press on button "Continue with PIN" system standard PIN dialog must appears. enter image description here
  • User enter his PIN and press "Continue" button.
  • After System must check if entered PIN is correct or no and continue working.

Researches

I have made some researches and find some articles on stackoverflow and other internet sources which say "There is no way to develop a new custom unlock mechanism on a non-rooted phone." or "I would be surprised if you could, because then you would be probably able to steal the pin code, and I don't think anyone would want that.".

Also I have watched some video tutorials like Tutorial: Android Internals - Building a Custom ROM, Pt. 1 of 2 and Tutorial: Android Internals - Building a Custom ROM, Pt. 2 of 2.

EDITED

I have made some researches today and found very interesting thing, I think I am on a right way to the solution, and I want to share my ideas with you. So looking in android sources I found an interesting files ChooseLockPassword.java (packages\apps\Settings\src\com\android\settings) and LockPatternUtils.java (*frameworks\base\core\java\com\android\internal\widget*) now I am interest in:

Question

How can I call LockPatternUtils class function from my code ? Or Why I cant see that function in Eclipse ?


Decision

So I think that the only way to get access to the Android system PIN dialog is to root the phone make some changes in the system files and use system PIN dialod


Question

  1. Can somebody provide me useful links about getting access to the system PIN dialog in the rooted phone.
  2. Am I on a right way and can I solve my problem in this way ?
  3. If anybody encountered such problem please help me to solve.

Any Solutions ?

Okay, I have solved this problem and now I want to share my solution with you.

At first as I told I have android sources so I have made some changes in android sources to get access to the PIN and Pattern dialogs. And here they are:

in ~\AndroidSources\pakages\apps\Settings\AndroidManifest.xml I have changed following lines of code

<activity android:name="ConfirmLockPattern"
          android:exported="true"> // This line was added by me.
</activity>

<activity android:name="ConfirmLockPassword"
          android:exported="true" // This line was added by me.
          android:them="@android:style/Them.NoTitleBar">
</activity>

<activity android:name="ChooseLockPattern"
          android:exported="true" // This line was added by me.
          android:label="@string/lockpattern_change_lock_pattern_label">
</activity>

This modifications allow me to call "ConfirmLockPattern", "ConfirmLockPassword" and "ChooseLockPattern" activities from my own application. After I compile android Source codes and launch system.img on my emulator.

In my application I have write following functions in order to call "ConfirmLockPattern" or "ChooseLockPattern" activities:

/**
 * Show PIN/Password confirmation dialog.
 */
void ShowConfirmLockPINActivity() {
    CustomLog.i(TAG, "Show Confirm Lock PIN Activity");
    Intent intent = new Intent(Intent.ACTION_RUN);
    intent.setComponent(new ComponentName("com.android.settings",
        "com.android.settings.ConfirmLockPassword"));
    startActivityForResult(intent, mRequestCode);
} /* ShowConfirmLockPINActivity() */

/**
 * Show set PIN/Password dialog.
 */
void ShowSetLockPINActivity() {
    CustomLog.i(TAG, "Show Set Lock PIN Activity");
    Intent intent = new Intent(Intent.ACTION_RUN);
    intent.setComponent(new ComponentName("com.android.settings",
        "com.android.settings.ChooseLockPassword"));
    startActivityForResult(intent, mRequestCode);
} /* ShowSetLockPINActivity() */

/**
 * Show Pattern Confirmation dialog.
 */
void ShowSetLockPatternActivity() {
    CustomLog.i(TAG, "Show Set Lock Pattern Activity");
    Intent intent = new Intent(Intent.ACTION_RUN);
    intent.setComponent(new ComponentName("com.android.settings",
        "com.android.settings.ConfirmLockPattern"));
    startActivityForResult(intent, mRequestCode);
} /* ShowSetLockPatternActivity() */

How can I get JHC to cooperate with the android ndk?

11 votes

JHC is a Haskell compiler which portable generates C code and then invokes a compiler backend to make an executable.

I need to dump the header files and libraries for JHC's runtime system, so the android ndk can use it to compile the generated C code.

Alternatively, I need to figure out how to link the android API into JHC.

Basically, how can I plug JHC into the android ndk backend?

Edit: I've made a standalone compiler using one of the ndk's build tools that JHC can use, "build/tools/make-standalone-toolchain.sh" . Now I need to figure out a way for JHC to compile my program into a shared object library, and how to get JHC to not demand a "main" function.

Edit2: I have the following targets.ini and compile script. Strangely the shared library fails to load.

[android]
cc=arm-linux-androideabi-gcc
cflags+= -shared -fPIC -rdynamic -Wno-all
gc=static
executable_extension=.so
merge=mle32

and

#!/bin/sh

jhc --cross -mandroid \
 --main=Main.android_main \
 hs/Main.hs -o libs/armeabi/libnative-activity &&   
ant debug &&
ant debug install

I figured out the problem. I didn't put the function call "app_dummy()" at the start of my "android_main" function.

How to Support GESTURE, left/right slip, many transition effect in Android application

10 votes

In My application i want to flip the view.. I have seen such animation in Go SMS pro in Android. And Same thing i want in to my android application.

I want to flip the whole activity view. is it possible ? I have seen some example for the flip in android. But in that all example the view is in the same activity. Is it possible to set such view for the different activity. or to do such effect while going from one activity to another ?

Please see the snap for the Flip effect in Androidenter image description here:

If Yes then please give reference to any demo example or code.

I have got a question whether it is possible to create a 3D transition effect between two Activities. There is a sample program that does it among the API Demos but this program plays the transition effect between two views of the same Activity. The adaptation to do the same between two activities is not very complicated but has some tricks...

Check out Rotate3dAnimation.java, it was actually copied from the API Demos sample. It uses a Camera (not the hardware camera but an object of the 2D graphics toolkit) to take the views of the layout from different angles. What it does now is a flip. Using the same mechanism, you can implement the cube too. The only problem is that for a cube animation you need both the outgoing and the incoming layout which makes nice separation into standalone activities sort of hard to do (the animation must work on both the incoming and the outgoing layout at the same time).

How to get camera result as a uri in data folder?

9 votes

I am creating an application in which I want to capture a image and then I want to send that image in the email as a attachment.

I am opening a camera using android.provider.MediaStore.ACTION_IMAGE_CAPTURE intent action and I am passing the Uri of the file as a parameter EXTRA_OUTPUT to get the image back to the file. This is working perfectly and I am able to get the captured image if I use the external storage uri as a EXTRA_OUTPUT but if I use the data folder uri it is not working and the camera is not closing and its all buttons are not working.

Here is my code for get the result in the external storage directory

Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File out = Environment.getExternalStorageDirectory();
out = new File(out, imagename);
i.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(out));
startActivityForResult(i, CAMERA_RESULT);

And this code is for get the image in the data folder

Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File out = getFilesDir();
out = new File(out, MyPharmacyOptions.PRESCRIPTION_IMAGE_NAME);
i.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(out));
startActivityForResult(i, CAMERA_RESULT);

I knew that the data folder is not accessible to third application so may be this causes an issue so I have create one content provider to share the file.

Here is my content provide class

public class MyContentProvider extends ContentProvider {
    private static final String Tag = RingtonContentProvider.class.getName();
    public static final Uri CONTENT_URI = Uri
            .parse("content://x.y.z/");
    private static final HashMap<String, String> MIME_TYPES = new HashMap<String, String>();

    static {
        MIME_TYPES.put(".mp3", "audio/mp3");
        MIME_TYPES.put(".wav", "audio/mp3");
        MIME_TYPES.put(".jpg", "image/jpeg");
    }

    @Override
    public boolean onCreate() {
        return true;
    }

    @Override
    public String getType(Uri uri) {
        String path = uri.toString();

        for (String extension : MIME_TYPES.keySet()) {
            if (path.endsWith(extension)) {
                return (MIME_TYPES.get(extension));
            }
        }

        return (null);
    }

    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode)
            throws FileNotFoundException {
        File f = new File(getContext().getFilesDir(), uri.getPath());

        if (f.exists()) {
            return (ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY));
        }

        throw new FileNotFoundException(uri.getPath());
    }

    @Override
    public Cursor query(Uri url, String[] projection, String selection,
            String[] selectionArgs, String sort) {
        throw new RuntimeException("Operation not supported");
    }

    @Override
    public Uri insert(Uri uri, ContentValues initialValues) {
        File file = new File(getContext().getFilesDir(), uri.getPath());
        if(file.exists()) file.delete();
        try {
            file.createNewFile();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return Uri.fromFile(file);
    }

    @Override
    public int update(Uri uri, ContentValues values, String where,
            String[] whereArgs) {
        throw new RuntimeException("Operation not supported");
    }

    @Override
    public int delete(Uri uri, String where, String[] whereArgs) {
        File f = new File(getContext().getFilesDir(), "image1.jpg");
        if(f.exists()) f.delete();
        f = new File(getContext().getFilesDir(), "image2.jpg");
        if(f.exists()) f.delete();

        getContext().getContentResolver().notifyChange(CONTENT_URI, null);

    }
}

So to use this content provide I am using following code to pass the uri to the camera activity

Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
Uri uri = MyContentProvider.CONTENT_URI;
uri = Uri.withAppendedPath(uri, imagename);
getContentResolver().insert(uri, null);
getContentResolver().notifyChange(RingtonContentProvider.CONTENT_URI, null);
Log.d(Tag, uri.toString());
i.putExtra(MediaStore.EXTRA_OUTPUT, uri);

startActivityForResult(i, CAMERA_RESULT);

Now if I pass the url other then external storage directory the camera is opening but it is not closing in emulator but in device the camera is going to closed but I am not getting the result.

I have declared this content provide in the manifest file

<provider
android:name=".contentproviders.MyContentProvider"
android:authorities="x.y.z" />

Also I have given the permission to write the external storage and also for use the camera.

I am able to capture the image using the external storage but I want to store the image in the data directory instead of external storage because if the external storage in not available I want to capture the image and want to send mail.

If I create content provide then I can also share my image to the email application.

If we not provide the extras with the camera intent it will return the image as a byte[] in the activity result as a data extra but this is for the purpose of the thumbnail so I can't get the high resolution image using this way.

Please have a look into my question and give your suggestions. Thanks.

There are two ways to solve this problem. You can get the bitmap from the onActivityResult if you start the camera activity using ACTION_IMAGE-CAPTURE. Using content provider you can save the image to the phone's internal memory(File directory of your application) from the camera activity.

1. The first solution is very easy. start the camera activity using this code

Intent cameraIntent=new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);

fter capturing image you will get the result in the ActivtyResult.

if (requestCode == CAMERA_REQUEST) {  
    Bitmap photo = (Bitmap) data.getExtras().get("data"); 
 }

Note:: This first solution is working fine but the bitmap you are getting in onActivityResult() is of low resolution. If you want high resolution image then you should prefer a second solution.

2. Second solution is little bit long but it is very important.

In this case you will have to create a content provider which will use to share your local (Application's internal) file to the camera activity.

Here below is my Content provider class which I have changed and make it correct.

public class MyFileContentProvider extends ContentProvider {
    public static final Uri CONTENT_URI = Uri.parse
                                    ("content://com.example.camerademo/");
    private static final HashMap<String, String> MIME_TYPES = 
                                     new HashMap<String, String>();

    static {
        MIME_TYPES.put(".jpg", "image/jpeg");
        MIME_TYPES.put(".jpeg", "image/jpeg");
    }

    @Override
    public boolean onCreate() {

        try {
            File mFile = new File(getContext().getFilesDir(), "newImage.jpg");
            if(!mFile.exists()) {
                mFile.createNewFile();
            }
            getContext().getContentResolver().notifyChange(CONTENT_URI, null);
            return (true);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }

    @Override
    public String getType(Uri uri) {
        String path = uri.toString();

        for (String extension : MIME_TYPES.keySet()) {
            if (path.endsWith(extension)) {
                return (MIME_TYPES.get(extension));
            }
        }
        return (null);
    }

    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode)
    throws FileNotFoundException {

        File f = new File(getContext().getFilesDir(), "newImage.jpg");
        if (f.exists()) {
            return (ParcelFileDescriptor.open(f,
                    ParcelFileDescriptor.MODE_READ_WRITE));
        }
        throw new FileNotFoundException(uri.getPath());
    }
}

And to start the camera activity use simply

Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
i.putExtra(MediaStore.EXTRA_OUTPUT, MyFileContentProvider.CONTENT_URI);
startActivityForResult(i, CAMERA_RESULT);

For more information you can refer this blog

Note :: Don't test in emulator it will not work in emulator it will work in device only.

How should an Android application respond to critical changes in the environment?

9 votes

Let's say there's an application that creates an account in AccountManager. User explores the quite complicated activity graph of this application for a while, then goes to Accounts and Sync in Android Settings, removes the account and signs in (still being in Accounts and Sync as a different user.

I have defined a receiver for LOGIN_ACCOUNTS_CHANGED broadcast and I'm able to shut down all services gracefully. But activities are still there, bearing the name of the first user in their header (UI gets messed up in a number of ways, but this one is the most obvious).

So, the question is: what should be done about these orphan activities?

  • I could use something like clearTaskOnLaunch, but all activities are in the background when the change happens.
  • Set a flag in SharedPreferences and check in onResume() of each activity, then launch clearTask activity if needed? Too messy.
  • The best option I was able to come up with is to use android.os.Process.killProcess(android.os.Process.myPid()) to kill all activities. This is not too graceful, but gets job done. The only side effect is that activity stack is still there, when the most reasonable thing seems to be to start from the LAUNCHER activity, with clear history.

So, what would be the best way to respond to the described scenario?

Have all your activities extend from a MyActivity class which has a BroadcastReceiver member: mChangeReceiver.

Have MyActivity register mChangeReceiver in onCreate (and unregister in onDestroy), to the LOGIN_ACCOUNTS_CHANGED intent.

Have the mChangeReceiver call some abstract method onAccountChanged() that all extending classes need to override and implement to reflect the change in the GUI.

That's it. Now, whenever the account changes, all your living activities will get their onAccountChanged method called and will refresh their GUI.

Sending a android.content.Context parameter to a function with JNI

9 votes

I am trying to create a method that checks for internet connection that needs a Context parameter. The JNIHelper allows me to call static functions with parameters, but I don't know how to "retrieve" Cocos2d-x Activity class to use it as a parameter.

public static boolean isNetworkAvailable(Context context) {
    boolean haveConnectedWifi = false;
    boolean haveConnectedMobile = false;
    ConnectivityManager cm =
        (ConnectivityManager) context.getSystemService(
    Context.CONNECTIVITY_SERVICE);
    NetworkInfo[] netInfo = cm.getAllNetworkInfo();
    for (NetworkInfo ni : netInfo) {
        if (ni.getTypeName().equalsIgnoreCase("WIFI"))
            if (ni.isConnected())
                haveConnectedWifi = true;
        if (ni.getTypeName().equalsIgnoreCase("MOBILE"))
            if (ni.isConnected())
                haveConnectedMobile = true;
    }
    return haveConnectedWifi || haveConnectedMobile;
}

and the c++ code is

JniMethodInfo methodInfo;
if ( !JniHelper::getStaticMethodInfo( methodInfo,
    "my/app/TestApp", "isNetworkAvailable", "(Landroid/content/Context;)Z")) {
        //error
        return;
}
CCLog( "Method found and loaded!");
methodInfo.env->CallStaticBooleanMethod( methodInfo.classID,
methodInfo.methodID);
methodInfo.env->DeleteLocalRef( methodInfo.classID);

Cocos2dxActivity.java: Add this line to Cocos2dxActivity: private static Activity me = null; Remove this line from onCreate:

Cocos2dxActivity.context = getApplicationContext();

In its place put: me = this;

use :

(ConnectivityManager) me.getSystemService(
    Context.CONNECTIVITY_SERVICE);

Now you don't need to pass the context from your Jni... I know this is not the solution but for your case you don't need to worry about context from Jni.. You can simply do your work.

Hope this helps.. I used this way to send mail from android in my game. :)

PhoneGap 1.4 wrapping Sencha Touch 2.X - What about performance?

8 votes

I'm building a multiplatform tablet app wrapping it with Phonegap 1.4 using just its webview, then I work my magic with the Sencha Touch 2 framework. By multiplatform I mean iOS 5.X+ and Android 3.0+ (for now).

This app is working great so far, all its features work on both systems but... On the Android tablet (Samsung GalaxyTab) its really slow. What's happening? Can I do something about it, or its just android's limit?

Thanks


*EDIT* (I'm trying to make this post somewhat useful to the comunity)

Sencha Touch, like many other Javascript Frameworks are not the best example of performance due to javascript itself.

Then Why use Senha Touch?

  • In my case: Multiplatform (iOS, Android, Windows Phone, Blackberry, Windows, Mac OSX, Linux. Sharing 80-90% of the code)

Mitigating performance issues due to lack of visual pre-process in Android systems:

  1. CSS3 heavy visual process:

    • Avoid Gradients
    • Avoid Shadows
    • Avoid Transformations and animations
  2. Good MVC practices:

    • Don't use more views and you actually showing
    • Pre-render / Pre-datafetch when possible to avoid render and data process simultaneously

Same here. I've tested many of my Sencha Touch 2 applications on Samsung GalaxyTab and the performance is really terrible. There's a fact (which maybe a part of actual reason) that, iOS does many pre-process and calculation before rendering to make it seems smoother to user's look and feel, while Android tends to render & process simultaneously on the go.

In general, it could be say that, to every cross-platform mobile apps built on Javascript, like Sencha Touch, iOS performance is significantly better than Android. However, Sencha Touch dev team is trying their best to improve this, hopefully it would be better in next releases. You could see this article about iOS & Android devices performance comparison.

http://www.sencha.com/blog/sencha-touch-2-developer-preview/

PS: While it's much relevant to the OS's limit, you can also optimize your app to make it perform better on Android devices. To my experience, the best practice is:

  • Do NOT use CSS3 too much.
  • Keep your DOM as minimal as possible.

Hope it helps.

How to add header and Footer to each activity in android

6 votes

I want to add a ImageButton, a button and a textview in each of my activity at top and bottom.I thought of using header and footer. So I want to add a header and footer in each of my Android Activity. I don't have any idea of how to do that. I don't need source code of how to write a header or footer. What i want to know is where i have to define that header and footer means do i need to add a header and footer in each xml file or do i need to define two header.xml or footer.xml and use these xml files in each of other xml files. Or is there any other way mean like using a reference from the java file of that activity. Any help Appreciated.

Define two separate files header.xml and footer.xml and and than use

`<include layout="@layout/header"/>

<include layout="@layout/footer"/>`

Android when should I be opening and closing db connections?

5 votes

Overview: Opening db connections in the onStart and in async tasks has gotten to be quite complex. Is it bad practice to have globally available db connections? If it is bad what is a better way?

Details: I have an application that connects to the sqlite3 database in several activities. At first there weren't many places where I needed to access the database so I was just opening and closing each time I needed access. Then there were more places that needed to access it so, as suggested on another Stack Overflow question, I started opening the database connections in the onStart method of the activity that needed a connection and closing it in the onStop method.

This worked fine until I started needing connections in some asynchronous tasks that outlived the activity. Since the onStop method for the activity had been called and connections had been closed, by the time the async task tried accessing the database it was failing. As a solution I created separate connections for each async task that were opened in the onPreExecute method and closed in the onPostExecute method.

This has resulted in a lot of opening and closing of connections, and I'm wondering if creating globally available db connections in the application context is a good idea. It would definitely clean up a lot of code and remove any unclosed db exceptions that are happening if I forget to close a connection or the app experiences a force close. Any one else tried this / see any problems with this approach?

I ran into similar problems some weeks ago. I use several classes that have persistence in a SQLite db.

As I wanted to decouple the activities from persistence I created static inner classes (called Managers) for those that need persistence . Each time I instantiate a Manager a db connection is created and after using the manager I explicitly close it. If I had global managers to access the tables, they should be synchronized due to concurrency and I do not know when I should close those db connections. So I did it this way.

Hope this helps!