Dialog leak issue usually occur when the dialog is shown and later the activity destroy without dismissing it. Most common leaks happen while dialog is showing then the configuration or orientation change occur. So, it causes the leak and sometime it may also cause the App to crash or go into an invalid state. You may notice the leak only by looking at the logcat. This mean that you do not dismiss your dialog correctly before your activity get destroy.
When the orientation change, the activity will be destroyed and re-created again. Before the activity is destroyed due to orientation change, it will save the current state first. So, when the activity is re-created it tries to restore instance state (onRestoreInstanceState()) from the previous activity. Notice that when the activity is re-created, it is a new activity and a new view. The exception may occur, if it try to update the old view (possibly, the dialog that did not dismiss) in the new activity, because the old view will have an invalid Context.
So, if your application have any pop up dialog, make sure that you dismiss it before your application get destroy. Here is what you can do.
1. Dismiss all dialogs completely if exist in onPause() or immediately after it is no longer need.
2. Since most common leaks happen while dialog is showing then the configuration or orientation change occur, another way to avoid dialog leak is NOT to destroy the activity when orientation change. If the activity is not destroyed, then there is no dialog leak and there is no re-creation of new activity, thus no issue neither. This can be achieved by using the attribute android:configChanges=”orientation|keyboardHidden” in the manifest file and using the Override method onConfigurationChanged() inside your activity. By using the attribute android:configChanges you will tell Android that you will handle the configuration change yourself so, don’t destroy the activity. And you can handle the configuration change in the Override method, or you may leave it blank if you prefer not to do anything.
Wednesday, March 28, 2012
Avoid dialog leak issue in Android?
OutOfMemoryError when using bitmap in Android?
The most common issue that you may face while working with bitmap is OutOfMemoryError. This issue occur because the garbage collector (GC) does not free the object associated with the bitmap and clear preference to pixel data fast enough, thus cause the memory allocated for the bitmap to grow until exceeding Virtual Memory limit.
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
In
order to avoid this issue, you need to do recycle() for every bitmap
as soon as it no long need. Notice that recycle () is used to free
the native object associated with this bitmap, and clear the
reference to the pixel data. This will not free the pixel data
synchronously; it simply allows it to be garbage collected if there
are no other references. The bitmap is marked as “dead”, meaning
it will throw an exception if getPixels() or setPixels() is called,
and will draw nothing. This operation cannot be reversed, so it
should only be called if you are sure there are no further uses for
the bitmap. This is an advanced call, and normally need not be
called, since the normal GC process will free up this memory when
there are no more references to this bitmap. See the code below:
public class bitmaptest extends Activity {
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// decode a jpg into bitmap
Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/myimage.jpg");
...
// indicate that the bitmap is no longer need and GC should
// free it asap
bitmap.recycle();
}
}
Bimap
is a little tricky, miss-use it may causes an exception. Generally
using bitmap is recommended only if you need to get detail data of
the image such as image
width,
height, and pixel data. Otherwise, bitmap should not be used in order
to avoid OutOfMemoryError. For an example, if you just want to
dispaly an image such as icon, you could you ImageView class instead
and it also provides various display options such as scaling
and
tinting. The following code below shows how to build an
ImageView
that
uses an image from drawable resources and add it to the layout.public class bitmaptest extends Activity {
private LinearLayout mLinearLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create a LinearLayout in which to add the ImageView
mLinearLayout = new LinearLayout(this);
// Instantiate an ImageView and define its properties
ImageView imageView = new ImageView(this);
imageView.setImageResource(R.drawable.my_image);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
imageView.setLayoutParams(new GridView.LayoutParams(200, 200));
// Add the ImageView to the layout and set the layout as
// the content view
mLinearLayout.addView(imageView);
setContentView(mLinearLayout);
}
}
Is starting a thread in broadcast receiver a good idea in Android?
Usually,
the purpose of using thread is to perform a heavy task in the
background without interrupting any UI activity. In addition, the
onReceive() is running on UI thread so any long time operation may
cause ANR (application not responding). Thus, most developers may
think of using a thread in the onReceive() to perform long time
operation to avoid the ANR issue. However, using a thread in
onReceive() may not be a good idea neither.
As
we already know that the broadcast receiver life cycle is very short,
and it is destroyed shortly after onReceive() end. Thus, putting a
thread in onReceive() will cause it to be in a state that not belong
to anything and it may be easily killed which end up cause unexpected
behavior. A better way to handle long time operation in onReceive()
is to start an Intent Service instead (NOT bind service). See an
example below on how to start a service from onReceive().
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// start an intent service
context.startService(new Intent(this, MyService.class));
}
}
public class MyService extends Service {
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// do something here
return START_STICKY;
}
}
Tuesday, March 27, 2012
How to convert Date and Time in Millisecond in android?
public long dateConvertor(String date) throws ParseException {
Date currentpastDate = null;
try {
SimpleDateFormat formatter = new SimpleDateFormat("d MMM yyyy h:mm a");
currentpastDate = (Date) formatter.parse(date);
} catch (Exception E) {
E.printStackTrace();
}
return currentpastDate.getTime();
}
Saturday, March 24, 2012
How to write text through Canvas in android?
public class CanvasGreetingActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}
private static class SampleView extends View {
public SampleView(Context context) {
super(context);
setDrawingCacheEnabled(true);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
String blackText = "black";
String redText = " red";
Paint mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setTextSize(30);
mPaint.setTypeface(Typeface.create(Typeface.SERIF,Typeface.ITALIC));
float canvasWidth = canvas.getWidth();
float blackTextWidth = mPaint.measureText(blackText);
float sentenceWidth = mPaint.measureText(blackText + redText);
float startPositionX = (canvasWidth - sentenceWidth) / 2;
mPaint.setTextAlign(Paint.Align.LEFT);
canvas.translate(0, 80);
mPaint.setColor(Color.BLACK);
canvas.drawText(blackText, startPositionX, 0, mPaint);
mPaint.setColor(Color.RED);
canvas.drawText(redText, startPositionX + blackTextWidth, 0,mPaint);
}
}
Friday, March 23, 2012
How to solve Android Window Leak ?
The
WindowLeaked exception in the log usually happens when you have some
sort of async task that is finishing after the activity that began it
is destroyed.
Solution for the above issue, we can dismiss the
progress dialog before finish the activity.
Issue
:
Activity
com.sample.ViewLeakIssueActivity has leaked window
com.android.internal.policy.impl.TvWindow$DecorView@6bc30788 that was
originally added here
E/WindowManager( 1687): at
android.view.ViewRoot.(ViewRoot.java:230)
E/WindowManager( 1687):
at
android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
-----
Sample
Leak Issue
public class ViewLeakIssueActivity extends Activity
{
volatile ProgressDialog pd;
@Override
protected void
onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
pd
= ProgressDialog.show(ViewLeakIssueActivity.this, "",
"test...", true);
new Thread() {
public void
run() {
try {
sleep(5000);
} catch
(InterruptedException e) {
// TODO Auto-generated catch
block
e.printStackTrace();
}
System.out.println("@@@@@@@@@@@"+ViewLeakIssueActivity.this+pd.isShowing());
pd.dismiss();
}
}.start();
finish();
}
}
Solution
for the above issue, we can dismiss the progress dialog before finish
the activity.
@Override
public void finish()
{
if(pd.isShowing()){
pd.dismiss();
}
super.finish();
}
How to make the scrollable TextView in android?
public
class MainActivity extends Activity {
/**
Called when the activity is first created. */
private
TextView mTextView;
@Override
public
void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mTextView
= (TextView) findViewById(R.id.textView1);
mTextView
.setText("this
is for testing \nthis is for testing \nthis is for testing \nthis is
for testing \nthis is for testing \nthis is for testing \n");
mTextView.setMovementMethod(new
ScrollingMovementMethod() {
public
void onTakeFocus(TextView widget, Spannable text, int dir) {
}
@Override
public
boolean onKeyDown(TextView widget, Spannable buffer,
int
keyCode, KeyEvent event) {
switch
(keyCode) {
case
KeyEvent.KEYCODE_DPAD_DOWN:
for
(int i = 0, scrollAmount = getScrollAmount(widget); i <
scrollAmount; i++) {
down(widget,
buffer);
}
return
true;
case
KeyEvent.KEYCODE_DPAD_UP:
for
(int i = 0, scrollAmount = getScrollAmount(widget); i <
scrollAmount; i++) {
up(widget,
buffer);
}
return
true;
default:
return
super.onKeyDown(widget, buffer, keyCode, event);
}
}
private
int getScrollAmount(TextView widget) {
final
int visibleLineCount = (int) ((1f * widget.getHeight()) / widget
.getLineHeight());
int
scrollAmount = visibleLineCount - 1;
if
(scrollAmount < 1) {
scrollAmount
= 1;
}
return
scrollAmount;
}
});
}
@Override
public
boolean onKeyDown(int keyCode, KeyEvent event) {
switch
(keyCode) {
case
KeyEvent.KEYCODE_DPAD_DOWN:
return
true;
case
KeyEvent.KEYCODE_DPAD_UP:
mTextView.dispatchKeyEvent(event);
return
true;
default:
return
super.onKeyDown(keyCode, event);
}
}
}
How to detect Gesture based action in Android?
I
have list of images in a listview with url. When the user wants view
the full image then user click the image on the list view
it
will take to me the anonther activity and open in a imageview. and as
a user wants to tee the next nexe or previous image with come back to
listview page
Solution
: I have created the HashMap Contains the list of images and pass the
selected images name as bundle string. In a detail view created the
async task the fetch image from the internet
implement
the gestureListener. In this article we discussing about that
Related
: gesture move action, gesture based action, example geatures
1.
Create a Activity implements OnClickListener
public
class MySample1Activity extends Activity implements OnClickListener {
........
}
2.
Initialize below required object for gestureListener
ViewConfiguration
vc;
static
int SWIPE_MAX_OFF_PATH = 250;
static
int SWIPE_MIN_DISTANCE = 100;
static
int SWIPE_THRESHOLD_VELOCITY = 100;
private
GestureDetector gestureDetector;
View.OnTouchListener
gestureListener;
3.
Set Densitybased velocity
vc
= ViewConfiguration.get(this);
SWIPE_MIN_DISTANCE
= vc.getScaledTouchSlop();
SWIPE_THRESHOLD_VELOCITY
= vc.getScaledMinimumFlingVelocity();
4.
Create a Custom GestureListener class which extends
SimpleOnGestureListener
class
MyGestureDetector extends SimpleOnGestureListener {
}
5.
Override the onFling() and implement the geature move action
@Override
public
boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float
velocityY) {
try
{
if
(Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return
false;
//
right to left swipe
if
(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
&&
Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
Toast.makeText(MySample1Activity.this,
"Left Swipe",
Toast.LENGTH_SHORT).show();
}
else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
&&
Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
Toast.makeText(MySample1Activity.this,
"Right Swipe",
Toast.LENGTH_SHORT).show();
}
}
catch (Exception e) {
//
nothing
}
return
false;
}
Full
SourceCode
public
class MySample1Activity extends Activity implements OnClickListener {
/**
Called when the activity is first created. */
TextView
tView;
ViewConfiguration
vc;
static
int SWIPE_MAX_OFF_PATH = 250;
static
int SWIPE_MIN_DISTANCE = 100;
static
int SWIPE_THRESHOLD_VELOCITY = 100;
private
GestureDetector gestureDetector;
View.OnTouchListener
gestureListener;
@Override
public
void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tView
= (TextView) findViewById(R.id.textview1);
vc
= ViewConfiguration.get(this);
SWIPE_MIN_DISTANCE
= vc.getScaledTouchSlop();
SWIPE_THRESHOLD_VELOCITY
= vc.getScaledMinimumFlingVelocity();
gestureDetector
= new GestureDetector(new MyGestureDetector());
gestureListener
= new View.OnTouchListener() {
public
boolean onTouch(View v, MotionEvent event) {
if
(gestureDetector.onTouchEvent(event)) {
return
true;
}
return
false;
}
};
tView.setOnClickListener(this);
tView.setOnTouchListener(gestureListener);
}
class
MyGestureDetector extends SimpleOnGestureListener {
@Override
public
boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float
velocityY) {
try
{
if
(Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return
false;
//
right to left swipe
if
(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
&&
Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
Toast.makeText(MySample1Activity.this,
"Left Swipe",
Toast.LENGTH_SHORT).show();
}
else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
&&
Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
Toast.makeText(MySample1Activity.this,
"Right Swipe",
Toast.LENGTH_SHORT).show();
}
}
catch (Exception e) {
//
nothing
}
return
false;
}
}
@Override
public
void onClick(View v) {
//
TODO Auto-generated method stub
}
}
How to Hide showed Toast Messages in Android?
In
my App, there is a list, when a user clicks on an button, a toast
message is being displayed, 10 items - 10 toast messages, so if
the user clicks 10 times, then presses the button... he/she has to
wait for some seconds, until he's able to read the menu option text.
I
have found the below solution to hide the shows toast message.
public
class SampleToastActivity extends Activity {
Toast
myToast;
static
int i=0;
@Override
public
void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button
b1 = (Button) findViewById(R.id.button2);
b1.setOnClickListener(new
View.OnClickListener() {
@Override
public
void onClick(View v) {
i++;
if(myToast!=null){
myToast.cancel();
myToast.setText("Count"+i);
}else{
myToast
= Toast.makeText(SampleToastActivity.this, "Sample"+i, 10);
}
myToast.show();
}
});
}
}
Combining 2 Images in Android using Canvas ?
Below are the methods to canvert the two bitmap in to one..........
private BitmapDrawable createUserMarker(Bitmap bmp1, Bitmap bmp2) {
Bitmap bitmapStar = bmp1;
Bitmap bmOverlay = Bitmap.createBitmap(bmp2.getWidth(), bmp2.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bmOverlay);
canvas.drawARGB(0x00, 0, 0, 0);
canvas.drawBitmap(bmp2, 0, 0, null);
canvas.drawBitmap(bitmapStar, 2, 2, null);
BitmapDrawable dr = new BitmapDrawable(bmOverlay);
dr.setBounds(0, 0, dr.getIntrinsicWidth(), dr.getIntrinsicHeight());
return (dr);
}
OR
public Bitmap combineImages(Bitmap c, Bitmap s) {
// can add a 3rd parameter 'String loc' if you want to save the new
// image - left some code to do that at the bottom
Bitmap cs = null;
int width, height = 0;
if(c.getWidth() > s.getWidth()) {
width = c.getWidth();
height = c.getHeight() + s.getHeight();
} else {
width = s.getWidth();
height = c.getHeight() + s.getHeight();
}
cs = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas comboImage = new Canvas(cs);
comboImage.drawBitmap(c, 0f, 0f, null);
comboImage.drawBitmap(s, 0f, c.getHeight(), null);
// this is an extra bit I added, just incase you want to save the new image somewhere and then return the location
/*String tmpImg = String.valueOf(System.currentTimeMillis()) + ".png";
OutputStream os = null;
try {
os = new FileOutputStream(loc + tmpImg);
cs.compress(CompressFormat.PNG, 100, os);
} catch(IOException e) {
Log.e("combineImages", "problem combining images", e);
}*/
return cs;
}
Thursday, March 22, 2012
How to use Non-Blocking Web-Request in android?
This
code fetches content from the web without blocking the UI (runs in
the background in a Thread). Once finished, it posts a Handler that
is picked up by the UI as soon as possible.
import
java.io.BufferedInputStream;
import
java.io.InputStream;
import
java.net.URL;
import
java.net.URLConnection;
import
org.apache.http.util.ByteArrayBuffer;
public
class Iconic extends Activity {
private
String html = "";
private
Handler mHandler;
public
void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mHandler
= new Handler();
checkUpdate.start();
}
private
Thread checkUpdate = new Thread() {
public
void run() {
try
{
URL
updateURL = new URL("http://iconic.4feets.com/update");
URLConnection
conn = updateURL.openConnection();
InputStream
is = conn.getInputStream();
BufferedInputStream
bis = new BufferedInputStream(is);
ByteArrayBuffer
baf = new ByteArrayBuffer(50);
int
current = 0;
while((current
= bis.read()) != -1){
baf.append((byte)current);
}
/*
Convert the Bytes read to a String. */
html
= new String(baf.toByteArray());
mHandler.post(showUpdate);
}
catch (Exception e) {
}
}
};
private
Runnable showUpdate = new Runnable(){
public
void run(){
Toast.makeText(Iconic.this, "HTML Code: " + html,
Toast.LENGTH_SHORT).show();
}
};
}
Wednesday, March 21, 2012
Reference Integrity Example in Android Sqlite?
Declaring
Referential Integrity (Foreign Key) Constraints
Foreign
key constraints are used to check referential integrity between
tables in a database. Consider for example the following two tables:
create
table Residence (
name
VARCHAR PRIMARY KEY,
capacity
INT
);
create
table Student (
id
INT PRIMARY KEY,
firstName
VARCHAR,
lastName
VARCHAR,
residence
VARCHAR
);
We
can enforce the constraint that a Student's residence actually exists
by making Student.residence a
foreign key that refers to Residence.name.
SQLite lets you specify this relationship in several different ways:
create
table Residence (
name
VARCHAR PRIMARY KEY,
capacity
INT
);
create
table Student (
id
INT PRIMARY KEY,
firstName
VARCHAR,
lastName
VARCHAR,
residence
VARCHAR,
FOREIGN
KEY(residence) REFERENCES Residence(name)
);
or
create
table Residence (
name
VARCHAR PRIMARY KEY,
capacity
INT
);
create
table Student (
id
INT PRIMARY KEY,
firstName
VARCHAR,
lastName
VARCHAR,
residence
VARCHAR REFERENCES Residence(name)
);
or
create
table Residence (
name
VARCHAR PRIMARY KEY,
capacity
INT
);
create
table Student (
id
INT PRIMARY KEY,
firstName
VARCHAR,
lastName
VARCHAR,
residence
VARCHAR REFERENCES Residence -- Implicitly references the primary
key of the Residence table.
);
All
three forms are valid syntax for specifying the same constraint. More
details can be found in the documentation for SQLite
Foreign Key Support .
Constraint
Enforcement
There
are a number of important things about how referential integrity and
foreign keys are handled in SQLite:
- The attribute(s) referenced by a foreign key constraint (i.e. Residence.name in the example above) must be declared unique or as a primary key within their table, but this requirement is checked at run-time, not when constraints are declared. For example, if Residence.name had not been declared as the primary key (or as unique), the FOREIGN KEY declarations above would still be permitteed, but inserting into the Student table would always yield an error.
- Foreign key constraints are not checked by default. If you want SQLite to check any foreign key constraints specified on your tables, you must enable them with the command:PRAGMA foreign_keys = ON;once per database session (i.e. once per invocation of /usr/class/cs145/bin/sqlite). Even if you have previously enabled foreign key constraint checking while using a particular database, new sessions with that database will not check foreign key constraints unless you issue this PRAGMA command. If you do not issue this command, foreign key constraints are permitted to become violated, and it will happen in complete silence.
- Bulk-Loading into a SQLite database while checking referential integrity is very, very slow -- we don't recommend it. It is faster to bulk-load your data with referential integrity checking turned off, then run SQL queries over your tables to verify that the constraints hold, then turn constraint-checking on.
- Referential integrity checking can be "deferred". This means that the constraint is not checked until the current transaction ends, or if there is no active transaction, when the current statement ends. This can be useful when adding tuples to multiple tables -- so that you don't need to worry about the order of inserts, or in the case of referential integrity between two tables in both directions.A foreign key constraint can be made deferrable with the keywordsDEFERRABLE INITIALLY DEFERRED:create table Residence (name VARCHAR PRIMARY KEY,capacity INT);create table Student (id INT PRIMARY KEY,firstName VARCHAR,lastName VARCHAR,residence VARCHAR REFERENCES Residence DEFERRABLE INITIALLY DEFERRED);By doing so, we can write:BEGIN;insert into Student values (123, 'Ben', 'Savage', 'Gavilan');insert into Residence values ('Gavilan', 50);COMMIT;and no error will be raised after the insertion into Student.
- Special action can be taken when the referenced tuple is updated or deleted. Let's say our Residence and Student tables contain the tuples inserted above:select * from Student;id firstName lastName residence------ --------- --------- ---------123 Ben Savage Gavilanselect * from Residence;name capacity------- --------Gavilan 50By default, updating or removing the tuple in Residence is not permitted, since it would leave the tuple in Student "dangling" and the database in an inconsistent state. SQLite supports ON UPDATE and ONDELETE actions that will keep the database in a consistent state:
- RESTRICT: This is the default behavior -- it prohibits a change to the Residence tuple, as long as there are Student tuples that depend on it.
- CASCADE: Changes to the Residence tuple will be propagated to all Student tuples that depend on it.
- SET NULL: A change to the Residence tuple will set the referencing value in Student.residence to null.ON UPDATE and ON DELETE actions can be specified along with a foreign key constraint declaration, as in these examples:
- residence VARCHAR REFERENCES Residence ON UPDATE RESTRICT
- residence VARCHAR REFERENCES Residence ON DELETE CASCADE
- residence VARCHAR REFERENCES Residence ON UPDATE SET NULL ON DELETE RESTRICT
Again,
more details on referential integrity in SQLite can be found in
the SQLite
Foreign Key Support documentation.
Subscribe to:
Posts (Atom)