org.uguess.android.sysinfo.SiragonInfo.java Source code

Java tutorial

Introduction

Here is the source code for org.uguess.android.sysinfo.SiragonInfo.java

Source

/********************************************************************************
 * (C) Copyright 2000-2010.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ********************************************************************************/

package org.uguess.android.sysinfo;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.TabHost;
import android.widget.TabWidget;
import android.widget.TextView;

import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Date;

/**
 * QSystemInfo
 */
public final class SiragonInfo extends FragmentActivity {

    private static final String PREF_KEY_LAST_ACTIVE = "last_active_tab"; //$NON-NLS-1$

    // private static Method mtdGetActionBar = null;
    // private static Method mtdSetDisplayShowTitleEnabled = null;getSystemA2SDStorageInfo
    // private static Method mtdSetNavigationMode = null;
    private static Method mtdSetListNavigationCallbacks = null;
    private static Method mtdSetSelectedNavigationItem = null;

    static {
        if (Util.SDK_VER >= 11) {
            // try
            // {
            //            mtdGetActionBar = Activity.class.getDeclaredMethod( "getActionBar" ); //$NON-NLS-1$
            //            Class<?> clz = Class.forName( "android.app.ActionBar" ); //$NON-NLS-1$
            //            mtdSetDisplayShowTitleEnabled = clz.getDeclaredMethod( "setDisplayShowTitleEnabled", //$NON-NLS-1$
            // boolean.class );
            //            mtdSetNavigationMode = clz.getDeclaredMethod( "setNavigationMode", //$NON-NLS-1$
            // int.class );
            //            mtdSetListNavigationCallbacks = clz.getDeclaredMethod( "setListNavigationCallbacks", //$NON-NLS-1$
            // SpinnerAdapter.class,
            //                  Class.forName( "android.app.ActionBar$OnNavigationListener" ) ); //$NON-NLS-1$
            //            mtdSetSelectedNavigationItem = clz.getDeclaredMethod( "setSelectedNavigationItem", //$NON-NLS-1$
            // int.class );
            // }
            // catch ( Exception e )
            // {
            // Log.e( QSystemInfo.class.getName( ),
            //                  "Current SDK version do not support Action Bar framework." ); //$NON-NLS-1$
            // }
        }
    }

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

        Util.hookExceptionHandler(getApplicationContext());

        if (Util.SDK_VER < 11) {
            requestWindowFeature(Window.FEATURE_NO_TITLE);
        }

        setContentView(R.layout.main);

        TabHost th = (TabHost) findViewById(android.R.id.tabhost);
        th.setup();

        ViewPager vp = (ViewPager) findViewById(R.id.pager);

        ITabContainer tabContainer = null;

        if (Util.SDK_VER >= 11) {
            // if ( mtdGetActionBar != null
            // && mtdSetDisplayShowTitleEnabled != null
            // && mtdSetNavigationMode != null
            // && mtdSetListNavigationCallbacks != null
            // && mtdSetSelectedNavigationItem != null )
            // {
            // try
            // {
            // Object actionBar = mtdGetActionBar.invoke( this );
            //
            // mtdSetDisplayShowTitleEnabled.invoke( actionBar, false );
            // mtdSetNavigationMode.invoke( actionBar,
            // ActionBar.NAVIGATION_MODE_LIST );
            //
            // tabContainer = new NavListAdapter( this,
            // actionBar,
            // vp,
            // new String[]{
            // getString( R.string.tab_info ),
            // getString( R.string.tab_apps ),
            // getString( R.string.tab_procs ),
            // getString( R.string.tab_netstat )
            // } );
            // }
            // catch ( Exception e )
            // {
            // Log.e( QSystemInfo.class.getName( ),
            // e.getLocalizedMessage( ),
            // e );
            // }
            // }
        }

        if (tabContainer == null) {
            tabContainer = new TabsAdapter(this, th, vp);
        }

        tabContainer.addTab(th.newTabSpec(SiragonManager.class.getName()).setIndicator(getString(R.string.tab_info),
                getResources().getDrawable(R.drawable.info)), SiragonManager.class, null);

        tabContainer.addTab(th.newTabSpec(ApplicationManager.class.getName())
                .setIndicator(getString(R.string.tab_apps), getResources().getDrawable(R.drawable.applications)),
                ApplicationManager.class, null);

        tabContainer.addTab(th.newTabSpec(ProcessManager.class.getName())
                .setIndicator(getString(R.string.tab_procs), getResources().getDrawable(R.drawable.processes)),
                ProcessManager.class, null);

        tabContainer.addTab(th.newTabSpec(NetStateManager.class.getName())
                .setIndicator(getString(R.string.tab_netstat), getResources().getDrawable(R.drawable.connection)),
                NetStateManager.class, null);

        SharedPreferences sp = getSharedPreferences(SiragonManager.PSTORE_SYSINFOMANAGER, Context.MODE_PRIVATE);

        fixTextView(th);

        Util.updateIcons(this, sp);

        if (sp != null) {
            int tab = sp.getInt(SiragonManager.PREF_KEY_DEFAULT_TAB, 0);

            if (tab == 0) {
                tab = sp.getInt(PREF_KEY_LAST_ACTIVE, 1);
            }

            if (tab > 0 && tab < 5) {
                th.setCurrentTab(tab - 1);
            }
        }
    }

    @Override
    protected void onDestroy() {
        SharedPreferences sp = getSharedPreferences(SiragonManager.PSTORE_SYSINFOMANAGER, Context.MODE_PRIVATE);

        if (sp != null) {
            int tab = sp.getInt(SiragonManager.PREF_KEY_DEFAULT_TAB, 0);

            if (tab == 0) {
                Editor et = sp.edit();
                et.putInt(PREF_KEY_LAST_ACTIVE, ((TabHost) findViewById(android.R.id.tabhost)).getCurrentTab() + 1);
                et.commit();
            }
        }

        super.onDestroy();
    }

    private void fixTextView(View view) {
        if (view instanceof TextView) {
            TextView tv = (TextView) view;
            tv.setSingleLine();
            Util.setAllCaps(tv, false);
        } else if (view instanceof ViewGroup) {
            ViewGroup vg = (ViewGroup) view;

            for (int i = 0, size = vg.getChildCount(); i < size; i++) {
                fixTextView(vg.getChildAt(i));
            }
        }
    }

    /**
     * ITabContainer
     */
    interface ITabContainer {

        void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args);
    }

    /**
     * TabInfo
     */
    static final class TabInfo {

        private Class<?> clss;
        private Bundle args;

        TabInfo(Class<?> _class, Bundle _args) {
            clss = _class;
            args = _args;
        }
    }

    /**
     * TabFactory
     */
    static final class TabFactory implements TabHost.TabContentFactory {

        private Context ctx;

        public TabFactory(Context context) {
            ctx = context;
        }

        @Override
        public View createTabContent(String tag) {
            View v = new View(ctx);
            v.setMinimumWidth(0);
            v.setMinimumHeight(0);
            return v;
        }
    }

    /**
     * NavListAdapter
     */
    static final class NavListAdapter extends FragmentPagerAdapter
            implements ViewPager.OnPageChangeListener, ITabContainer {

        private Context ctx;
        private Object bar;
        private ViewPager pager;
        private ArrayList<TabInfo> tabs = new ArrayList<TabInfo>();

        NavListAdapter(FragmentActivity activity, Object bar, ViewPager pager, String[] items) {
            super(activity.getSupportFragmentManager());

            this.ctx = activity;
            this.bar = bar;
            this.pager = pager;

            pager.setAdapter(this);
            pager.setOnPageChangeListener(this);

            ArrayAdapter<String> adapter = new ArrayAdapter<String>(ctx,
                    android.R.layout.simple_spinner_dropdown_item, items);

            try {
                Class<?> clz = Class.forName("android.app.ActionBar$OnNavigationListener"); //$NON-NLS-1$
                Object listener = Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[] { clz },
                        new InvocationHandler() {

                            @Override
                            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                                if ("onNavigationItemSelected".equals(method.getName())) //$NON-NLS-1$
                                {
                                    NavListAdapter.this.pager.setCurrentItem((Integer) args[0]);
                                    return true;
                                }
                                return null;
                            }
                        });

                mtdSetListNavigationCallbacks.invoke(bar, adapter, listener);
            } catch (Exception e) {
                Log.e(SiragonInfo.class.getName(), e.getLocalizedMessage(), e);
            }
        }

        @Override
        public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
            TabInfo info = new TabInfo(clss, args);
            tabs.add(info);
            notifyDataSetChanged();
        }

        @Override
        public void onPageScrollStateChanged(int arg0) {
        }

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {
        }

        @Override
        public void onPageSelected(int position) {
            try {
                mtdSetSelectedNavigationItem.invoke(bar, position);
            } catch (Exception e) {
                Log.e(SiragonInfo.class.getName(), e.getLocalizedMessage(), e);
            }
        }

        @Override
        public Fragment getItem(int position) {
            TabInfo info = tabs.get(position);
            return Fragment.instantiate(ctx, info.clss.getName(), info.args);
        }

        @Override
        public int getCount() {
            return tabs.size();
        }
    }

    /**
     * TabsAdapter
     */
    static final class TabsAdapter extends FragmentPagerAdapter
            implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener, ITabContainer {

        private Context ctx;
        private TabHost th;
        private ViewPager vp;
        private ArrayList<TabInfo> tabs = new ArrayList<TabInfo>();

        public TabsAdapter(FragmentActivity activity, TabHost tabHost, ViewPager pager) {
            super(activity.getSupportFragmentManager());

            ctx = activity;
            th = tabHost;
            vp = pager;

            th.setOnTabChangedListener(this);
            vp.setAdapter(this);
            vp.setOnPageChangeListener(this);
        }

        @Override
        public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
            tabSpec.setContent(new TabFactory(ctx));

            TabInfo info = new TabInfo(clss, args);
            tabs.add(info);
            th.addTab(tabSpec);
            notifyDataSetChanged();
        }

        @Override
        public int getCount() {
            return tabs.size();
        }

        @Override
        public Fragment getItem(int position) {
            TabInfo info = tabs.get(position);
            return Fragment.instantiate(ctx, info.clss.getName(), info.args);
        }

        @Override
        public void onTabChanged(String tabId) {
            int position = th.getCurrentTab();
            vp.setCurrentItem(position);
        }

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        }

        @Override
        public void onPageSelected(int position) {
            // Unfortunately when TabHost changes the current tab, it kindly
            // also takes care of putting focus on it when not in touch mode.
            // The jerk.
            // This hack tries to prevent this from pulling focus out of our
            // ViewPager.
            TabWidget widget = th.getTabWidget();
            int oldFocusability = widget.getDescendantFocusability();
            widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
            th.setCurrentTab(position);
            widget.setDescendantFocusability(oldFocusability);
        }

        @Override
        public void onPageScrollStateChanged(int state) {
        }
    }

    /**
     * ErrorHandler
     */
    static final class ErrorHandler implements UncaughtExceptionHandler, Constants {

        private UncaughtExceptionHandler parentHandler;
        private Context ctx;

        ErrorHandler(Context ctx, UncaughtExceptionHandler parentHandler) {
            this.parentHandler = parentHandler;
            this.ctx = ctx;
        }

        public void uncaughtException(Thread thread, Throwable ex) {
            Intent it = new Intent(Intent.ACTION_VIEW);
            it.setClass(ctx, ErrorReportActivity.class);
            it.setFlags(it.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            it.putExtra("thread", thread.toString()); //$NON-NLS-1$
            it.putExtra("exception", Log.getStackTraceString(ex)); //$NON-NLS-1$

            PendingIntent pi = PendingIntent.getActivity(ctx, 0, it, 0);

            Notification nc = new Notification(R.drawable.logo2, "error", //$NON-NLS-1$
                    System.currentTimeMillis());

            nc.flags |= Notification.FLAG_AUTO_CANCEL;
            nc.setLatestEventInfo(ctx, ctx.getString(R.string.oops), ctx.getString(R.string.oops_msg), pi);

            ((NotificationManager) ctx.getSystemService(NOTIFICATION_SERVICE)).notify(NOTIFY_ERROR_REPORT, nc);

            if (parentHandler != null) {
                parentHandler.uncaughtException(thread, ex);
            }
        }
    }

    /**
     * ErrorReportActivity
     */
    public static final class ErrorReportActivity extends Activity {

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

            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                    WindowManager.LayoutParams.FLAG_FULLSCREEN);

            Util.hookExceptionHandler(getApplicationContext());

            OnClickListener listener = new OnClickListener() {

                public void onClick(DialogInterface dialog, int which) {
                    if (which == DialogInterface.BUTTON_POSITIVE) {
                        sendBugReport();
                    }

                    ErrorReportActivity.this.finish();
                }
            };

            new AlertDialog.Builder(this).setTitle(R.string.bug_title).setMessage(R.string.bug_detail)
                    .setPositiveButton(R.string.agree, listener).setNegativeButton(android.R.string.no, listener)
                    .setCancelable(false).create().show();
        }

        void sendBugReport() {
            StringBuffer msg = new StringBuffer();
            Intent it = new Intent(Intent.ACTION_SENDTO);
            String content = null;

            try {
                String title = "Bug Report - " + new Date().toLocaleString(); //$NON-NLS-1$

                it.setData(Uri.parse("mailto:qauck.aa@gmail.com")); //$NON-NLS-1$

                it.putExtra(Intent.EXTRA_SUBJECT, title);

                SiragonManager.createTextHeader(this, msg, title);

                msg.append("\n-----THREAD-----\n") //$NON-NLS-1$
                        .append(getIntent().getStringExtra("thread")); //$NON-NLS-1$

                msg.append("\n\n-----EXCEPTION-----\n") //$NON-NLS-1$
                        .append(getIntent().getStringExtra("exception")); //$NON-NLS-1$
                ;

                // try get the intermediate report first
                content = msg.toString();

                msg.append("\n\n-----LOGCAT-----\n"); //$NON-NLS-1$

                Process proc = Runtime.getRuntime().exec("logcat -d -v time *:V"); //$NON-NLS-1$

                SiragonManager.readRawText(msg, proc.getInputStream());

                msg.append("\n-----LOGCAT-END-----\n"); //$NON-NLS-1$
            } catch (Throwable e) {
                try {
                    msg.append("\n\n-----ERROR-COLLECT-REPORT-----\n"); //$NON-NLS-1$
                    msg.append(Log.getStackTraceString(e));
                    msg.append("\n-----ERROR-END-----\n"); //$NON-NLS-1$
                } catch (Throwable t) {
                    // must be OOM, doing nothing
                }
            } finally {
                try {
                    // get the final report
                    content = msg.toString();
                } catch (Throwable t) {
                    // mostly still be OOM, doing nothing
                } finally {
                    if (content != null) {
                        try {
                            it.putExtra(Intent.EXTRA_TEXT, content);

                            it = Intent.createChooser(it, null);
                            startActivity(it);

                            return;
                        } catch (Throwable t) {
                            // failed at last stage, log and give up
                            Log.e(getClass().getName(), t.getLocalizedMessage(), t);
                        }
                    }

                    Util.shortToast(this, R.string.bug_failed);
                }
            }
        }
    }

    /**
     * BootReceiver
     */
    public static final class BootReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            SharedPreferences sp = context.getSharedPreferences(SiragonManager.PSTORE_SYSINFOMANAGER,
                    Context.MODE_PRIVATE);

            if (sp != null && sp.getBoolean(SiragonManager.PREF_KEY_AUTO_START_ICON, false)) {
                Util.updateIcons(context, sp);
            }
        }
    }
}