Showing posts with label Android development. Show all posts
Showing posts with label Android development. Show all posts

Friday, September 19, 2014

Android - Load libraries at runtime

The Android compiler has a limitation of 65536 methods per .dex file. You can find a solution here, which tends to build your application to multiple dex files. However, if you need to add external libaries that make your application exceeds the limitation, we can come to another solution: copy the libraries somewhere except libs folder (assets folder, or sdcard), and load them at runtime. It seems easy, but we need to do some required steps to make it work.

1. Add dex file to libary jar file

We use dx command to create a dex file for the library:

dx --dex --output=classes.dex library.jar

Then, append it to the ordiginal library jar file with aapt command:

aapt add library.jar classes.dex

Notice that dx and aapt command are built tools of Android sdk, so they must in the classpath.

2. Load library file at runtime

Thanks to Nick Caballero for a nice solution to load a libary at runtime. You can go here to get Dexter class, which can be used as follow:


public class MainActivity extends Activity {
    private static String library = "library.jar";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         try {
             Dexter.loadFromAssets(this, library);
         } catch (Exception e) {
             throw new RuntimeException("Unable to load DEX files", e);
         }

         try {
              startActivity(new Intent(MainActivity.this,                                getClassLoader().loadClass("the real activity")));
         } catch (ClassNotFoundException e) {
              throw new RuntimeException("Unable to start", e);
         }
    }

}

Hope this helps!

Tuesday, December 3, 2013

How does a hash table work?

Today I found an awesome answer for this question on stackoverflow.com, you can see it here http://stackoverflow.com/questions/730620/how-does-a-hash-table-work. I just re-post here for later reference.


Now, start!

Let's assume you want to fill up a library of books, and not just stuff them in there, but you want to be able to easily find them again when you need them.
So, you decide that if the person that wants to read a book knows the title of the book, and the exact title to boot, then that's all it should take. With the title, the person, with the aid of the librarian, should be able to go find the book easily and quickly.
So, how can you do that? Well, obviously you can keep some kind of list of where you put each book, but then you have the same problem as searching the library, you need to search the list. Granted, the list would be smallers, and easier to search, but still, you don't want to search sequentially from one end of the library (or list) to the other.
You want something that, with the title of the book, can give you the right spot at once, so all you have to do is just stroll over to the right shelf, and pick up the book.
But how can that be done? Well, with a bit of forethought when you fill up the library, and actually, a lot of work when you fill up the library.
Instead of just starting to fill up the library from one end to the other, you devise a clever little method. You take the title of the book, run it through a small computer program, which spits out a shelf number and a slot number on that shelf. This is where you place the book.
The beauty of this program is that later on, when a person comes back in to read the book, you feed the title through the program once more, and get back the same shelf number and slot number that you were originally given, and this is where the book is located.
The program, as others have already mentioned, is called a hash algorithm or hash computation, and usually works by taking the data fed into it (the title of the book in this case) and calculates a number from it.
For simplicity, let's say that it just converts each letter and symbol into a number, and sums them all up. In reality it's a lot more complicated than that, but let's leave it at that for now.
The beauty of such an algorithm is that if you feed the same input into it again and again, it will keep spitting out the same number each time.
Ok, so that's basically how a hash table works.
Technical stuff follows.
First, there's the size of the number. Usually, the output of such a hash algorithm is inside a range of some large number, typically much much larger than the space you have in your table. For instance, let's say that we have room for exactly one million books in the library. The output of the hash calculation could be in the range of 0 to one billion, a lot higher.
So what do we do? We use something called modulus calculation, which basically says that if you counted to the number you wanted (ie. the one billion number), but wanted to stay inside a much smaller range, each time you hit the limit of that smaller range, you started back at 0, but you have to keep track of how far in the big sequence you've come.
Say that the output of the hash algorithm is in the range of 0 to 20, and you get the value 17 from a particular title. If the size of the library is only 7 books, you count 0, 1, 2, 3, 4, 5, 6, and when you get to 7, you start back at 0. Since we need to count 17 times, we have 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, and the final number is 3.
Of course modulus calculation isn't done like that, it's done with division, and remainder. The remainder of dividing 17 by 7 is 3 (7 goes 2 times into 17, to 14, and the difference between 17 and 14 is 3).
Thus, you put the book in slot nr. 3.
This leads to the next problem. Collisions. Since the algorithm has no way to space out the books so that they fill the library exactly (or the hash table if you will), it will invariably end up calculating a number that has been used before. In the library sense, when you get to the shelf and the slot number you wish to put a book in, there's already a book there.
Various collision handling methods exist, including running the data into yet another calculation to get another spot in the table, or simply to find a space close to the one you were given (i.e. right next to the previous book). This would mean that you have some digging to do when you try to find the book later, but it's still better than simply starting at one end of the library.
Finally, at some point, you might want to put more books into the library than the library allows, in other words, you need to build a bigger library. Since the exact spot in the library was calculated using the exact, and current, size of the library, it goes to follow that if you resize the library, you might end up having to find new spots for all the books, since the calculation done to find their spots has changed.

Sunday, April 21, 2013

Android view lifecycle

What is View?

View class represents the basic building block for user interface components. A View occupies a rectangular area on the screen and is responsible for drawing and event handling. View is the base class for widgets, which are used to create interactive UI components (buttons, text fields, etc.). The ViewGroup subclass is the base class for layouts, which are invisible containers that hold other Views (or other ViewGroups) and define their layout properties.

Using Views

All of the views in a window are arranged in a single tree. You can add views either from code or by specifying a tree of views in one or more XML layout files. There are many specialized subclasses of views that act as controls or are capable of displaying text, images, or other content.

Once you have created a tree of views, there are typically a few types of common operations you may wish to perform:

  • Set properties: for example setting the text of a TextView. The available properties and the methods that set them will vary among the different subclasses of views. Note that properties that are known at build time can be set in the XML layout files.
  • Set focus: The framework will handled moving focus in response to user input. To force focus to a specific view, call requestFocus().
  • Set up listeners: Views allow clients to set listeners that will be notified when something interesting happens to the view. For example, all views will let you set a listener to be notified when the view gains or loses focus. You can register such a listener using setOnFocusChangeListener(android.view.View.OnFocusChangeListener). Other view subclasses offer more specialized listeners. For example, a Button exposes a listener to notify clients when the button is clicked.
  • Set visibility: You can hide or show views using setVisibility(int).

Note: The Android framework is responsible for measuring, laying out and drawing views. You should not call methods that perform these actions on views yourself unless you are actually implementing a ViewGroup.

Implementing a Custom View

To implement a custom view, you will usually begin by providing overrides for some of the standard methods that the framework calls on all views. You do not need to override all of these methods. In fact, you can start by just overriding onDraw(android.graphics.Canvas).

CategoryMethodsDescription
CreationConstructorsThere is a form of the constructor that are called when the view is created from code and a form that is called when the view is inflated from a layout file. The second form should parse and apply any attributes defined in the layout file.
onFinishInflate()Called after a view and all of its children has been inflated from XML.
LayoutonMeasure(int, int)Called to determine the size requirements for this view and all of its children.
onLayout(boolean, int, int, int, int)Called when this view should assign a size and position to all of its children.
onSizeChanged(int, int, int, int)Called when the size of this view has changed.
DrawingonDraw(android.graphics.Canvas)Called when the view should render its content.
Event processingonKeyDown(int, KeyEvent)Called when a new hardware key event occurs.
onKeyUp(int, KeyEvent)Called when a hardware key up event occurs.
onTrackballEvent(MotionEvent)Called when a trackball motion event occurs.
onTouchEvent(MotionEvent)Called when a touch screen motion event occurs.
FocusonFocusChanged(boolean, int, android.graphics.Rect)Called when the view gains or loses focus.
onWindowFocusChanged(boolean)Called when the window containing the view gains or loses focus.
AttachingonAttachedToWindow()Called when the view is attached to a window.
onDetachedFromWindow()Called when the view is detached from its window.
onWindowVisibilityChanged(int)Called when the visibility of the window containing the view has changed.

View lifecycle



Source

Android Activity Lifecycle

Activities in the system are managed as an activity stack. When a new activity is started, it is placed on the top of the stack and becomes the running activity -- the previous activity always remains below it in the stack, and will not come to the foreground again until the new activity exits.

An activity has essentially four states: 
  • If an activity in the foreground of the screen (at the top of the stack), it is active or running.
  • If an activity has lost focus but is still visible (that is, a new non-full-sized or transparent activity has focus on top of your activity), it is paused. A paused activity is completely alive (it maintains all state and member information and remains attached to the window manager), but can be killed by the system in extreme low memory situations.
  • If an activity is completely obscured by another activity, it is stopped. It still retains all state and member information, however, it is no longer visible to the user so its window is hidden and it will often be killed by the system when memory is needed elsewhere.
  • If an activity is paused or stopped, the system can drop the activity from memory by either asking it to finish, or simply killing its process. When it is displayed again to the user, it must be completely restarted and restored to its previous state.
The following diagram shows the important state paths of an Activity. The square rectangles represent callback methods you can implement to perform operations when the Activity moves between states. The colored ovals are major states the Activity can be in.




There are three key loops you may be interested in monitoring within your activity:


  • The entire lifetime of an activity happens between the first call to onCreate(Bundle) through to a single final call to onDestroy(). An activity will do all setup of "global" state in onCreate(), and release all remaining resources in onDestroy(). For example, if it has a thread running in the background to download data from the network, it may create that thread in onCreate() and then stop the thread in onDestroy().
  • The visible lifetime of an activity happens between a call to onStart() until a corresponding call to onStop(). During this time the user can see the activity on-screen, though it may not be in the foreground and interacting with the user. Between these two methods you can maintain resources that are needed to show the activity to the user. For example, you can register a BroadcastReceiver in onStart() to monitor for changes that impact your UI, and unregister it in onStop() when the user no longer sees what you are displaying. The onStart() and onStop() methods can be called multiple times, as the activity becomes visible and hidden to the user.
  • The foreground lifetime of an activity happens between a call to onResume() until a corresponding call to onPause(). During this time the activity is in front of all other activities and interacting with the user. An activity can frequently go between the resumed and paused states -- for example when the device goes to sleep, when an activity result is delivered, when a new intent is delivered -- so the code in these methods should be fairly lightweight.


The entire lifecycle of an activity is defined by the following Activity methods. All of these are hooks that you can override to do appropriate work when the activity changes state. All activities will implement onCreate(Bundle) to do their initial setup; many will also implement onPause() to commit changes to data and otherwise prepare to stop interacting with the user. You should always call up to your superclass when implementing these methods.
 public class Activity extends ApplicationContext {
     protected void onCreate(Bundle savedInstanceState);

     protected void onStart();
     
     protected void onRestart();

     protected void onResume();

     protected void onPause();

     protected void onStop();

     protected void onDestroy();
 }
 
Source: Android Developer