Android: rotation failure, horizontal and vertical

I play with android and I am creating a simple Twitter application to check what I have learned so far. But I ran into a problem that I do not understand. I created a stream to receive tweets, no problem there, but then added a ProgressDialog to show when this stream was working. This caused a very unusual behavior. If the user rotates from vertical orientation to horizontal orientation, the program behaves as expected, no problems, but if he then turns back, the program will fail, saying that a window has leaked.

The problem only occurs when switching horizontally and vertically. I know about the problems if you try to rotate while the dialog box is running, but I made sure that the dialog box finished working and got fired before it rotated, and it would still break. Here is my code:

package com.onesmartpuppy.puppytweet; import java.util.ArrayList; import com.github.droidfu.widgets.WebImageView; import winterwell.jtwitter.Twitter; import winterwell.jtwitter.Twitter.Status; import android.app.ListActivity; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.View.OnClickListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.TextView; public class PuppyTweet extends ListActivity implements OnClickListener { private ProgressDialog m_ProgressDialog = null; private ArrayList<Status> messages = null; private TweetAdapter m_adapter; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); messages = new ArrayList<Status>(); this.m_adapter = new TweetAdapter(this, R.layout.row, messages); setListAdapter(this.m_adapter); setupButtons(); m_ProgressDialog = ProgressDialog.show(this, "Please wait...", "Retrieving tweets ...", true); Runnable findTweets = new Runnable(){ @Override public void run() { try { messages = new ArrayList<Status>(); Twitter ourTwitter = new Twitter("*****", "******"); messages = (ArrayList<Status>) ourTwitter.getFriendsTimeline(); Thread.sleep(1000); Log.i("ARRAY", ""+ messages.size()); } catch (Exception e) { Log.e("BACKGROUND_PROC", e.getMessage()); } handler.sendEmptyMessage(0); } }; Thread thread = new Thread(null, findTweets, "FindTweets"); thread.start(); } private void setupButtons() { Button refreshButton = (Button) findViewById(R.id.refresh_button); refreshButton.setOnClickListener(this); Button settingsButton = (Button) findViewById(R.id.settings_button); settingsButton.setOnClickListener(this); Button tweetButton = (Button) findViewById(R.id.update_button); tweetButton.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.settings_button: break; case R.id.update_button: break; case R.id.refresh_button: break; default: break; } } private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { if(messages != null && messages.size() > 0){ m_adapter.clear(); m_adapter.notifyDataSetChanged(); for(int i=0;i<messages.size();i++) m_adapter.add(messages.get(i)); } m_ProgressDialog.dismiss(); m_adapter.notifyDataSetChanged(); } }; private class TweetAdapter extends ArrayAdapter<Status> { private ArrayList<Status> items; public TweetAdapter(Context context, int textViewResourceId, ArrayList<Status> items) { super(context, textViewResourceId, items); this.items = items; } @Override public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; if (v == null) { LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(R.layout.row2, null); } Status o = (Status) items.get(position); if (o != null) { WebImageView img = (WebImageView) v.findViewById(R.id.webimage); TextView tt = (TextView) v.findViewById(R.id.toptext); TextView bt = (TextView) v.findViewById(R.id.bottomtext); if (tt != null) { tt.setText("Name: " + o.user.name); } if(bt != null){ bt.setText("Status: " + o.getText()); } if (img !=null) { img.setImageUrl(o.getUser().profileImageUrl.toString()); img.loadImage(); } } return v; } } } 

sees LogCat, where it crashes from:

 02-10 16:01:05.237: INFO/ActivityManager(63): Config changed: { scale=1.0 imsi=310/260 loc=ld_US touch=3 keys=2/1/2 nav=3/1 orien=2 layout=18} 02-10 16:01:05.344: WARN/UsageStats(63): Something wrong here, didn't expect com.onesmartpuppy.puppytweet to be resumed 02-10 16:01:05.384: INFO/WindowManager(63): Setting rotation to 0, animFlags=0 02-10 16:01:05.394: INFO/ActivityManager(63): Config changed: { scale=1.0 imsi=310/260 loc=ld_US touch=3 keys=2/1/2 nav=3/1 orien=1 layout=18} 02-10 16:01:05.504: WARN/UsageStats(63): Something wrong here, didn't expect com.onesmartpuppy.puppytweet to be resumed 02-10 16:01:05.704: ERROR/WindowManager(227): Activity com.onesmartpuppy.puppytweet.PuppyTweet has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@43af9490 that was originally added here 02-10 16:01:05.704: ERROR/WindowManager(227): android.view.WindowLeaked: Activity com.onesmartpuppy.puppytweet.PuppyTweet has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@43af9490 that was originally added here 02-10 16:01:05.704: ERROR/WindowManager(227): at android.view.ViewRoot.<init>(ViewRoot.java:227) 02-10 16:01:05.704: ERROR/WindowManager(227): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148) 02-10 16:01:05.704: ERROR/WindowManager(227): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91) 02-10 16:01:05.704: ERROR/WindowManager(227): at android.view.Window$LocalWindowManager.addView(Window.java:424) 02-10 16:01:05.704: ERROR/WindowManager(227): at android.app.Dialog.show(Dialog.java:239) 02-10 16:01:05.704: ERROR/WindowManager(227): at android.app.ProgressDialog.show(ProgressDialog.java:107) 02-10 16:01:05.704: ERROR/WindowManager(227): at android.app.ProgressDialog.show(ProgressDialog.java:90) 02-10 16:01:05.704: ERROR/WindowManager(227): at com.onesmartpuppy.puppytweet.PuppyTweet.onCreate(PuppyTweet.java:39) 02-10 16:01:05.704: ERROR/WindowManager(227): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) 02-10 16:01:05.704: ERROR/WindowManager(227): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2417) 02-10 16:01:05.704: ERROR/WindowManager(227): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2470) 02-10 16:01:05.704: ERROR/WindowManager(227): at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3573) 02-10 16:01:05.704: ERROR/WindowManager(227): at android.app.ActivityThread.access$2300(ActivityThread.java:119) 02-10 16:01:05.704: ERROR/WindowManager(227): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1825) 02-10 16:01:05.704: ERROR/WindowManager(227): at android.os.Handler.dispatchMessage(Handler.java:99) 02-10 16:01:05.704: ERROR/WindowManager(227): at android.os.Looper.loop(Looper.java:123) 02-10 16:01:05.704: ERROR/WindowManager(227): at android.app.ActivityThread.main(ActivityThread.java:4310) 02-10 16:01:05.704: ERROR/WindowManager(227): at java.lang.reflect.Method.invokeNative(Native Method) 02-10 16:01:05.704: ERROR/WindowManager(227): at java.lang.reflect.Method.invoke(Method.java:521) 02-10 16:01:05.704: ERROR/WindowManager(227): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 02-10 16:01:05.704: ERROR/WindowManager(227): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 02-10 16:01:05.704: ERROR/WindowManager(227): at dalvik.system.NativeStart.main(Native Method) 02-10 16:01:06.344: INFO/global(227): Default buffer size used in BufferedReader constructor. It would be better to be explicit if an 8k-char buffer is required. 02-10 16:01:06.624: DEBUG/dalvikvm(227): GC freed 6082 objects / 479568 bytes in 77ms 02-10 16:01:07.374: DEBUG/dalvikvm(227): GC freed 11982 objects / 709808 bytes in 83ms 02-10 16:01:07.394: INFO/global(227): Default buffer size used in BufferedReader constructor. It would be better to be explicit if an 8k-char buffer is required. 02-10 16:01:07.564: DEBUG/dalvikvm(227): GC freed 95 objects / 79880 bytes in 68ms 02-10 16:01:07.704: DEBUG/dalvikvm(227): GC freed 8 objects / 38992 bytes in 65ms 02-10 16:01:08.174: DEBUG/dalvikvm(63): GC freed 5407 objects / 257208 bytes in 174ms 02-10 16:01:08.194: INFO/ARRAY(227): 20 02-10 16:01:08.204: DEBUG/AndroidRuntime(227): Shutting down VM 02-10 16:01:08.204: WARN/dalvikvm(227): threadid=3: thread exiting with uncaught exception (group=0x4001b188) 02-10 16:01:08.204: ERROR/AndroidRuntime(227): Uncaught handler: thread main exiting due to uncaught exception 02-10 16:01:08.214: ERROR/AndroidRuntime(227): java.lang.IllegalArgumentException: View not attached to window manager 02-10 16:01:08.214: ERROR/AndroidRuntime(227): at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:355) 02-10 16:01:08.214: ERROR/AndroidRuntime(227): at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:200) 02-10 16:01:08.214: ERROR/AndroidRuntime(227): at android.view.Window$LocalWindowManager.removeView(Window.java:432) 02-10 16:01:08.214: ERROR/AndroidRuntime(227): at android.app.Dialog.dismissDialog(Dialog.java:280) 02-10 16:01:08.214: ERROR/AndroidRuntime(227): at android.app.Dialog.access$000(Dialog.java:73) 02-10 16:01:08.214: ERROR/AndroidRuntime(227): at android.app.Dialog$1.run(Dialog.java:109) 02-10 16:01:08.214: ERROR/AndroidRuntime(227): at android.app.Dialog.dismiss(Dialog.java:264) 02-10 16:01:08.214: ERROR/AndroidRuntime(227): at com.onesmartpuppy.puppytweet.PuppyTweet$1.handleMessage(PuppyTweet.java:104) 02-10 16:01:08.214: ERROR/AndroidRuntime(227): at android.os.Handler.dispatchMessage(Handler.java:99) 02-10 16:01:08.214: ERROR/AndroidRuntime(227): at android.os.Looper.loop(Looper.java:123) 02-10 16:01:08.214: ERROR/AndroidRuntime(227): at android.app.ActivityThread.main(ActivityThread.java:4310) 02-10 16:01:08.214: ERROR/AndroidRuntime(227): at java.lang.reflect.Method.invokeNative(Native Method) 02-10 16:01:08.214: ERROR/AndroidRuntime(227): at java.lang.reflect.Method.invoke(Method.java:521) 02-10 16:01:08.214: ERROR/AndroidRuntime(227): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 02-10 16:01:08.214: ERROR/AndroidRuntime(227): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 02-10 16:01:08.214: ERROR/AndroidRuntime(227): at dalvik.system.NativeStart.main(Native Method) 02-10 16:01:08.244: INFO/Process(63): Sending signal. PID: 227 SIG: 3 02-10 16:01:08.244: INFO/dalvikvm(227): threadid=7: reacting to signal 3 02-10 16:01:08.274: ERROR/dalvikvm(227): Unable to open stack trace file '/data/anr/traces.txt': Permission denied 02-10 16:01:08.754: DEBUG/dalvikvm(227): GC freed 5986 objects / 372656 bytes in 316ms 02-10 16:01:09.829: INFO/ARRAY(227): 20 02-10 16:01:09.955: INFO/Process(227): Sending signal. PID: 227 SIG: 9 02-10 16:01:09.974: INFO/ActivityManager(63): Process com.onesmartpuppy.puppytweet (pid 227) has died. 02-10 16:01:10.014: INFO/WindowManager(63): WIN DEATH: Window{43b653e0 com.onesmartpuppy.puppytweet/com.onesmartpuppy.puppytweet.PuppyTweet paused=false} 02-10 16:01:10.014: INFO/WindowManager(63): WIN DEATH: Window{43c32b48 Please wait... paused=false} 02-10 16:01:10.164: WARN/UsageStats(63): Unexpected resume of com.android.launcher while already resumed in com.onesmartpuppy.puppytweet 02-10 16:01:10.314: WARN/InputManagerService(63): Got RemoteException sending setActive(false) notification to pid 227 uid 10023 
+7
java android progressdialog
source share
1 answer

A WindowLeaked exception in a log usually occurs when you have some kind of asynchronous task that ends after the activity that has started has been destroyed.

When you rotate the screen, activity is recreated. In Android docs, you must save any state of the instance in the onPause method, including making sure that any async tasks are stopped. You can recreate the onCreate method using the saved package.

+9
source share

All Articles