├── ic_launcher-web.png
├── res
├── drawable-hdpi
│ └── ic_launcher.png
├── drawable-ldpi
│ └── ic_launcher.png
├── drawable-mdpi
│ └── ic_launcher.png
├── drawable-xhdpi
│ └── ic_launcher.png
├── values
│ ├── strings.xml
│ └── styles.xml
├── layout
│ ├── activity_item_detail.xml
│ ├── activity_item_list.xml
│ ├── fragment_item_detail.xml
│ └── activity_item_twopane.xml
├── values-v11
│ └── styles.xml
├── values-large
│ └── refs.xml
├── values-sw600dp
│ └── refs.xml
└── values-v14
│ └── styles.xml
├── README.md
├── .gitignore
├── project.properties
├── LICENSE
├── tools
├── pushAndRun-debug
├── pushAndRun-release
├── build-debug
├── build-release
└── update.sh
├── ant.properties
├── proguard-project.txt
├── AndroidManifest.xml
└── src
└── jackpal
└── droidexaminer
├── ItemDetailFragment.java
├── ItemDetailActivity.java
├── ItemListActivity.java
├── ItemListFragment.java
└── content
└── Content.java
/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jackpal/droid-examiner/HEAD/ic_launcher-web.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jackpal/droid-examiner/HEAD/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jackpal/droid-examiner/HEAD/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jackpal/droid-examiner/HEAD/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jackpal/droid-examiner/HEAD/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Droid Examiner
5 | Item Detail
6 |
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | droid-examiner
2 | ==============
3 |
4 | An Android utility for examining Linux system internals of an Android device.
5 |
6 | This is the source code for the Droid Examiner android app.
7 |
8 | https://play.google.com/store/apps/details?id=jackpal.droidexaminer&hl=en
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build artifacts
2 | bin/
3 | gen/
4 | libs/
5 |
6 | # Signing key, kept secret
7 | tools/droid-examiner.keystore
8 |
9 | # Eclipse project files
10 | .classpath
11 | .project
12 | .settings/
13 |
14 | # Generated by tools/update.sh
15 | build.xml
16 | local.properties
17 |
18 | lint.xml
19 |
--------------------------------------------------------------------------------
/res/layout/activity_item_detail.xml:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/res/values-large/refs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 | - @layout/activity_item_twopane
11 |
12 |
--------------------------------------------------------------------------------
/res/values-sw600dp/refs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 | - @layout/activity_item_twopane
11 |
12 |
--------------------------------------------------------------------------------
/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/res/layout/activity_item_list.xml:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-16
15 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2013 Jack Palevich
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
--------------------------------------------------------------------------------
/res/layout/fragment_item_detail.xml:
--------------------------------------------------------------------------------
1 |
7 |
15 |
16 |
--------------------------------------------------------------------------------
/tools/pushAndRun-debug:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # command line build script for installing and running terminal emulator.
3 | set -e
4 |
5 | if [ -z "${ANDROID_SDK_ROOT+xxx}" ]; then
6 | echo "Please define ANDROID_SDK_ROOT to point to the Android SDK"
7 | exit 1
8 | fi
9 |
10 | if [ ! -d "$ANDROID_SDK_ROOT" ]; then
11 | echo "The directory $ANDROID_SDK_ROOT = ${ANDROID_NDK_ROOT} does not exist."
12 | exit 1
13 | fi
14 |
15 | ADB="$ANDROID_SDK_ROOT/platform-tools/adb"
16 |
17 | $ADB uninstall jackpal.droidexaminer
18 | $ADB install -r bin/DroidExaminer-debug.apk && $ADB shell am start -n jackpal.droidexaminer/jackpal.droidexaminer.ItemListActivity
19 |
--------------------------------------------------------------------------------
/tools/pushAndRun-release:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # command line build script for installing and running terminal emulator.
3 | set -e
4 |
5 | if [ -z "${ANDROID_SDK_ROOT+xxx}" ]; then
6 | echo "Please define ANDROID_SDK_ROOT to point to the Android SDK"
7 | exit 1
8 | fi
9 |
10 | if [ ! -d "$ANDROID_SDK_ROOT" ]; then
11 | echo "The directory $ANDROID_SDK_ROOT = ${ANDROID_NDK_ROOT} does not exist."
12 | exit 1
13 | fi
14 |
15 | ADB="$ANDROID_SDK_ROOT/platform-tools/adb"
16 |
17 | $ADB uninstall jackpal.droidexaminer
18 | $ADB install -r bin/DroidExaminer-release.apk && adb shell am start -n jackpal.droidexaminer/jackpal.droidexaminer.ItemListActivity
19 |
--------------------------------------------------------------------------------
/tools/build-debug:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # command line build script for building the debug version
3 | set -e
4 |
5 | if [ -z "${ANDROID_SDK_ROOT+xxx}" ]; then
6 | echo "Please define ANDROID_SDK_ROOT to point to the Android SDK"
7 | exit 1
8 | fi
9 |
10 | if [ ! -d "$ANDROID_SDK_ROOT" ]; then
11 | echo "The directory $ANDROID_SDK_ROOT = ${ANDROID_NDK_ROOT} does not exist."
12 | exit 1
13 | fi
14 |
15 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
16 | ATE_ROOT="$( cd $DIR/.. && pwd )"
17 |
18 | cd "$ATE_ROOT"
19 |
20 | if [ ! -f "local.properties" ]; then
21 | echo "local.properties does not exist. Please run tools/update.sh"
22 | exit 1
23 | fi
24 |
25 | rm -rf `find . -name bin -o -name obj -prune`
26 |
27 | ant debug
28 |
--------------------------------------------------------------------------------
/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
--------------------------------------------------------------------------------
/ant.properties:
--------------------------------------------------------------------------------
1 | # This file is used to override default values used by the Ant build system.
2 | #
3 | # This file must be checked in Version Control Systems, as it is
4 | # integral to the build system of your project.
5 |
6 | # This file is only used by the Ant script.
7 |
8 | # You can use this to override default values such as
9 | # 'source.dir' for the location of your java source folder and
10 | # 'out.dir' for the location of your output folder.
11 |
12 | # You can also use it define how the release builds are signed by declaring
13 | # the following properties:
14 | # 'key.store' for the location of your keystore and
15 | # 'key.alias' for the name of the key to use.
16 | # The password will be asked during the build when you use the 'release' target.
17 |
18 | key.alias=release
19 | key.store=tools/droid-examiner.keystore
20 |
--------------------------------------------------------------------------------
/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/tools/build-release:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # command line build script for building release version
3 | # This will only work on my (Jack Palevich) computer, because it
4 | # requires the private key store used o sign the release version
5 | # of Android Terminal Emulator.
6 | set -e
7 |
8 | if [ -z "${ANDROID_SDK_ROOT+xxx}" ]; then
9 | echo "Please define ANDROID_SDK_ROOT to point to the Android SDK"
10 | exit 1
11 | fi
12 |
13 | if [ ! -d "$ANDROID_SDK_ROOT" ]; then
14 | echo "The directory $ANDROID_SDK_ROOT = ${ANDROID_NDK_ROOT} does not exist."
15 | exit 1
16 | fi
17 |
18 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
19 | ATE_ROOT="$( cd $DIR/.. && pwd )"
20 |
21 | cd "$ATE_ROOT"
22 |
23 | if [ ! -f "local.properties" ]; then
24 | echo "local.properties does not exist. Please run tools/update.sh"
25 | exit 1
26 | fi
27 |
28 | rm -rf `find . -name bin -o -name obj -prune`
29 |
30 | ant release
31 |
--------------------------------------------------------------------------------
/tools/update.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # You have to run this once in order for ant builds to work
3 | set -e
4 |
5 | if [ -z "${ANDROID_SDK_ROOT+xxx}" ]; then
6 | echo "Please define ANDROID_SDK_ROOT to point to the Android SDK"
7 | exit 1
8 | fi
9 |
10 | if [ ! -d "$ANDROID_SDK_ROOT" ]; then
11 | echo "The directory $ANDROID_SDK_ROOT = ${ANDROID_SDK_ROOT} does not exist."
12 | exit 1
13 | fi
14 |
15 | ANDROID="$ANDROID_SDK_ROOT/tools/android"
16 |
17 | command -v "$ANDROID" >/dev/null 2>&1 || { echo >&2 "The $ANDROID tool is not found. Aborting."; exit 1; }
18 |
19 | ANDROID_TARGET=android-16
20 |
21 | # Make sure ANDROID_TARGET is installed
22 |
23 | $ANDROID update sdk -a -u -t $ANDROID_TARGET
24 |
25 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
26 | APP_ROOT="$( cd $DIR/.. && pwd )"
27 |
28 | # Copy the Android Support jar file from the SDK to our libs directory.
29 | mkdir -p $APP_ROOT/libs
30 |
31 | cp $ANDROID_SDK_ROOT/extras/android/support/v4/android-support-v4.jar $APP_ROOT/libs
32 |
33 | echo "Updating android project files"
34 |
35 | $ANDROID update project -p "$APP_ROOT" --target $ANDROID_TARGET
36 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
12 |
13 |
18 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
31 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/res/layout/activity_item_twopane.xml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
22 |
23 |
30 |
31 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/src/jackpal/droidexaminer/ItemDetailFragment.java:
--------------------------------------------------------------------------------
1 | package jackpal.droidexaminer;
2 |
3 | import android.os.Bundle;
4 | import android.support.v4.app.Fragment;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.TextView;
9 |
10 | import jackpal.droidexaminer.R;
11 | import jackpal.droidexaminer.content.Content;
12 |
13 | /**
14 | * A fragment representing a single Item detail screen.
15 | * This fragment is either contained in a {@link ItemListActivity}
16 | * in two-pane mode (on tablets) or a {@link ItemDetailActivity}
17 | * on handsets.
18 | */
19 | public class ItemDetailFragment extends Fragment {
20 | /**
21 | * The fragment argument representing the item ID that this fragment
22 | * represents.
23 | */
24 | public static final String ARG_ITEM_ID = "item_id";
25 |
26 | /**
27 | * The dummy content this fragment is presenting.
28 | */
29 | private Content.Item mItem;
30 |
31 | /**
32 | * Mandatory empty constructor for the fragment manager to instantiate the
33 | * fragment (e.g. upon screen orientation changes).
34 | */
35 | public ItemDetailFragment() {
36 | }
37 |
38 | @Override
39 | public void onCreate(Bundle savedInstanceState) {
40 | super.onCreate(savedInstanceState);
41 |
42 | if (getArguments().containsKey(ARG_ITEM_ID)) {
43 | // Load the dummy content specified by the fragment
44 | // arguments. In a real-world scenario, use a Loader
45 | // to load content from a content provider.
46 | mItem = Content.ITEM_MAP.get(getArguments().getString(ARG_ITEM_ID));
47 | }
48 | }
49 |
50 | @Override
51 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
52 | Bundle savedInstanceState) {
53 | View rootView = inflater.inflate(R.layout.fragment_item_detail, container, false);
54 |
55 | // Show the dummy content as text in a TextView.
56 | if (mItem != null) {
57 | ((TextView) rootView.findViewById(R.id.item_detail)).setText(mItem.getContents());
58 | }
59 |
60 | return rootView;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/jackpal/droidexaminer/ItemDetailActivity.java:
--------------------------------------------------------------------------------
1 | package jackpal.droidexaminer;
2 |
3 | import jackpal.droidexaminer.R;
4 | import jackpal.droidexaminer.content.Content;
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.support.v4.app.FragmentActivity;
8 | import android.support.v4.app.NavUtils;
9 | import android.view.MenuItem;
10 |
11 | /**
12 | * An activity representing a single Item detail screen. This
13 | * activity is only used on handset devices. On tablet-size devices,
14 | * item details are presented side-by-side with a list of items
15 | * in a {@link ItemListActivity}.
16 | *
17 | * This activity is mostly just a 'shell' activity containing nothing
18 | * more than a {@link ItemDetailFragment}.
19 | */
20 | public class ItemDetailActivity extends FragmentActivity {
21 |
22 | @Override
23 | protected void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 | Content.init(getApplicationContext());
26 | setContentView(R.layout.activity_item_detail);
27 |
28 | // Show the Up button in the action bar.
29 | getActionBar().setDisplayHomeAsUpEnabled(true);
30 |
31 | // savedInstanceState is non-null when there is fragment state
32 | // saved from previous configurations of this activity
33 | // (e.g. when rotating the screen from portrait to landscape).
34 | // In this case, the fragment will automatically be re-added
35 | // to its container so we don't need to manually add it.
36 | // For more information, see the Fragments API guide at:
37 | //
38 | // http://developer.android.com/guide/components/fragments.html
39 | //
40 | if (savedInstanceState == null) {
41 | // Create the detail fragment and add it to the activity
42 | // using a fragment transaction.
43 | Bundle arguments = new Bundle();
44 | arguments.putString(ItemDetailFragment.ARG_ITEM_ID,
45 | getIntent().getStringExtra(ItemDetailFragment.ARG_ITEM_ID));
46 | ItemDetailFragment fragment = new ItemDetailFragment();
47 | fragment.setArguments(arguments);
48 | getSupportFragmentManager().beginTransaction()
49 | .add(R.id.item_detail_container, fragment)
50 | .commit();
51 | }
52 | }
53 |
54 | @Override
55 | public boolean onOptionsItemSelected(MenuItem item) {
56 | switch (item.getItemId()) {
57 | case android.R.id.home:
58 | // This ID represents the Home or Up button. In the case of this
59 | // activity, the Up button is shown. Use NavUtils to allow users
60 | // to navigate up one level in the application structure. For
61 | // more details, see the Navigation pattern on Android Design:
62 | //
63 | // http://developer.android.com/design/patterns/navigation.html#up-vs-back
64 | //
65 | NavUtils.navigateUpTo(this, new Intent(this, ItemListActivity.class));
66 | return true;
67 | }
68 | return super.onOptionsItemSelected(item);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/jackpal/droidexaminer/ItemListActivity.java:
--------------------------------------------------------------------------------
1 | package jackpal.droidexaminer;
2 |
3 | import jackpal.droidexaminer.R;
4 | import jackpal.droidexaminer.content.Content;
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.support.v4.app.FragmentActivity;
8 |
9 |
10 | /**
11 | * An activity representing a list of Items. This activity
12 | * has different presentations for handset and tablet-size devices. On
13 | * handsets, the activity presents a list of items, which when touched,
14 | * lead to a {@link ItemDetailActivity} representing
15 | * item details. On tablets, the activity presents the list of items and
16 | * item details side-by-side using two vertical panes.
17 | *
18 | * The activity makes heavy use of fragments. The list of items is a
19 | * {@link ItemListFragment} and the item details
20 | * (if present) is a {@link ItemDetailFragment}.
21 | *
22 | * This activity also implements the required
23 | * {@link ItemListFragment.Callbacks} interface
24 | * to listen for item selections.
25 | */
26 | public class ItemListActivity extends FragmentActivity
27 | implements ItemListFragment.Callbacks {
28 |
29 | /**
30 | * Whether or not the activity is in two-pane mode, i.e. running on a tablet
31 | * device.
32 | */
33 | private boolean mTwoPane;
34 |
35 | @Override
36 | protected void onCreate(Bundle savedInstanceState) {
37 | super.onCreate(savedInstanceState);
38 | Content.init(getApplicationContext());
39 | setContentView(R.layout.activity_item_list);
40 |
41 | if (findViewById(R.id.item_detail_container) != null) {
42 | // The detail container view will be present only in the
43 | // large-screen layouts (res/values-large and
44 | // res/values-sw600dp). If this view is present, then the
45 | // activity should be in two-pane mode.
46 | mTwoPane = true;
47 |
48 | // In two-pane mode, list items should be given the
49 | // 'activated' state when touched.
50 | ((ItemListFragment) getSupportFragmentManager()
51 | .findFragmentById(R.id.item_list))
52 | .setActivateOnItemClick(true);
53 | }
54 |
55 | // TODO: If exposing deep links into your app, handle intents here.
56 | }
57 |
58 | /**
59 | * Callback method from {@link ItemListFragment.Callbacks}
60 | * indicating that the item with the given ID was selected.
61 | */
62 | @Override
63 | public void onItemSelected(String id) {
64 | if (mTwoPane) {
65 | // In two-pane mode, show the detail view in this activity by
66 | // adding or replacing the detail fragment using a
67 | // fragment transaction.
68 | Bundle arguments = new Bundle();
69 | arguments.putString(ItemDetailFragment.ARG_ITEM_ID, id);
70 | ItemDetailFragment fragment = new ItemDetailFragment();
71 | fragment.setArguments(arguments);
72 | getSupportFragmentManager().beginTransaction()
73 | .replace(R.id.item_detail_container, fragment)
74 | .commit();
75 |
76 | } else {
77 | // In single-pane mode, simply start the detail activity
78 | // for the selected item ID.
79 | Intent detailIntent = new Intent(this, ItemDetailActivity.class);
80 | detailIntent.putExtra(ItemDetailFragment.ARG_ITEM_ID, id);
81 | startActivity(detailIntent);
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/jackpal/droidexaminer/ItemListFragment.java:
--------------------------------------------------------------------------------
1 | package jackpal.droidexaminer;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.support.v4.app.ListFragment;
6 | import android.view.View;
7 | import android.widget.ArrayAdapter;
8 | import android.widget.ListView;
9 |
10 | import jackpal.droidexaminer.content.Content;
11 |
12 | /**
13 | * A list fragment representing a list of Items. This fragment
14 | * also supports tablet devices by allowing list items to be given an
15 | * 'activated' state upon selection. This helps indicate which item is
16 | * currently being viewed in a {@link ItemDetailFragment}.
17 | *
18 | * Activities containing this fragment MUST implement the {@link Callbacks}
19 | * interface.
20 | */
21 | public class ItemListFragment extends ListFragment {
22 |
23 | /**
24 | * The serialization (saved instance state) Bundle key representing the
25 | * activated item position. Only used on tablets.
26 | */
27 | private static final String STATE_ACTIVATED_POSITION = "activated_position";
28 |
29 | /**
30 | * The fragment's current callback object, which is notified of list item
31 | * clicks.
32 | */
33 | private Callbacks mCallbacks = sDummyCallbacks;
34 |
35 | /**
36 | * The current activated item position. Only used on tablets.
37 | */
38 | private int mActivatedPosition = ListView.INVALID_POSITION;
39 |
40 | /**
41 | * A callback interface that all activities containing this fragment must
42 | * implement. This mechanism allows activities to be notified of item
43 | * selections.
44 | */
45 | public interface Callbacks {
46 | /**
47 | * Callback for when an item has been selected.
48 | */
49 | public void onItemSelected(String id);
50 | }
51 |
52 | /**
53 | * A dummy implementation of the {@link Callbacks} interface that does
54 | * nothing. Used only when this fragment is not attached to an activity.
55 | */
56 | private static Callbacks sDummyCallbacks = new Callbacks() {
57 | @Override
58 | public void onItemSelected(String id) {
59 | }
60 | };
61 |
62 | /**
63 | * Mandatory empty constructor for the fragment manager to instantiate the
64 | * fragment (e.g. upon screen orientation changes).
65 | */
66 | public ItemListFragment() {
67 | }
68 |
69 | @Override
70 | public void onCreate(Bundle savedInstanceState) {
71 | super.onCreate(savedInstanceState);
72 |
73 | // TODO: replace with a real list adapter.
74 | setListAdapter(new ArrayAdapter(
75 | getActivity(),
76 | android.R.layout.simple_list_item_activated_1,
77 | android.R.id.text1,
78 | Content.ITEMS));
79 | }
80 |
81 | @Override
82 | public void onViewCreated(View view, Bundle savedInstanceState) {
83 | super.onViewCreated(view, savedInstanceState);
84 |
85 | // Restore the previously serialized activated item position.
86 | if (savedInstanceState != null
87 | && savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
88 | setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION));
89 | }
90 | }
91 |
92 | @Override
93 | public void onAttach(Activity activity) {
94 | super.onAttach(activity);
95 |
96 | // Activities containing this fragment must implement its callbacks.
97 | if (!(activity instanceof Callbacks)) {
98 | throw new IllegalStateException("Activity must implement fragment's callbacks.");
99 | }
100 |
101 | mCallbacks = (Callbacks) activity;
102 | }
103 |
104 | @Override
105 | public void onDetach() {
106 | super.onDetach();
107 |
108 | // Reset the active callbacks interface to the dummy implementation.
109 | mCallbacks = sDummyCallbacks;
110 | }
111 |
112 | @Override
113 | public void onListItemClick(ListView listView, View view, int position, long id) {
114 | super.onListItemClick(listView, view, position, id);
115 |
116 | // Notify the active callbacks interface (the activity, if the
117 | // fragment is attached to one) that an item has been selected.
118 | mCallbacks.onItemSelected(Content.ITEMS.get(position).id);
119 | }
120 |
121 | @Override
122 | public void onSaveInstanceState(Bundle outState) {
123 | super.onSaveInstanceState(outState);
124 | if (mActivatedPosition != ListView.INVALID_POSITION) {
125 | // Serialize and persist the activated item position.
126 | outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
127 | }
128 | }
129 |
130 | /**
131 | * Turns on activate-on-click mode. When this mode is on, list items will be
132 | * given the 'activated' state when touched.
133 | */
134 | public void setActivateOnItemClick(boolean activateOnItemClick) {
135 | // When setting CHOICE_MODE_SINGLE, ListView will automatically
136 | // give items the 'activated' state when touched.
137 | getListView().setChoiceMode(activateOnItemClick
138 | ? ListView.CHOICE_MODE_SINGLE
139 | : ListView.CHOICE_MODE_NONE);
140 | }
141 |
142 | private void setActivatedPosition(int position) {
143 | if (position == ListView.INVALID_POSITION) {
144 | getListView().setItemChecked(mActivatedPosition, false);
145 | } else {
146 | getListView().setItemChecked(position, true);
147 | }
148 |
149 | mActivatedPosition = position;
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/src/jackpal/droidexaminer/content/Content.java:
--------------------------------------------------------------------------------
1 | package jackpal.droidexaminer.content;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.FileNotFoundException;
6 | import java.io.FileReader;
7 | import java.io.IOException;
8 | import java.util.ArrayList;
9 | import java.util.Arrays;
10 | import java.util.Formatter;
11 | import java.util.HashMap;
12 | import java.util.List;
13 | import java.util.Locale;
14 | import java.util.Map;
15 |
16 | import android.app.ActivityManager;
17 | import android.content.Context;
18 | import android.content.Intent;
19 | import android.content.IntentFilter;
20 | import android.content.pm.ConfigurationInfo;
21 | import android.content.res.Configuration;
22 | import android.hardware.Camera;
23 | import android.hardware.Sensor;
24 | import android.hardware.SensorManager;
25 | import android.opengl.GLES10;
26 | import android.os.BatteryManager;
27 | import android.os.Build;
28 | import android.os.Environment;
29 | import android.os.StatFs;
30 | import android.text.format.DateFormat;
31 | import android.util.Log;
32 | import android.util.Pair;
33 | import android.view.Display;
34 | import android.view.InputDevice;
35 | import android.view.WindowManager;
36 |
37 | /**
38 | * Helper class for providing sample content for user interfaces created by
39 | * Android template wizards.
40 | *
41 | * TODO: Replace all uses of this class before publishing your app.
42 | */
43 | public class Content {
44 | private static Context sContext;
45 | private static java.text.DateFormat sDateFormat;
46 | private static java.text.DateFormat sTimeFormat;
47 |
48 | /**
49 | * An array of sample (dummy) items.
50 | */
51 | public static List- ITEMS = new ArrayList
- ();
52 |
53 | /**
54 | * A map of sample (dummy) items, by ID.
55 | */
56 | public static Map ITEM_MAP = new HashMap();
57 |
58 | private static void addItem(Item item) {
59 | ITEMS.add(item);
60 | ITEM_MAP.put(item.id, item);
61 | }
62 |
63 | /**
64 | * A dummy item representing a piece of content.
65 | */
66 | public static abstract class Item {
67 | public final String id;
68 | private final String mLabel;
69 |
70 | public Item(String id, String label) {
71 | this.id = id;
72 | this.mLabel = label;;
73 | }
74 |
75 | public String getLabel() {
76 | return mLabel;
77 | }
78 |
79 | public abstract String getContents();
80 |
81 | @Override
82 | public String toString() {
83 | return mLabel;
84 | }
85 | }
86 |
87 | private static class PIS extends Pair {
88 | public PIS(int i, String s) {
89 | super(i, s);
90 | }
91 | };
92 |
93 | private static String formatBitmask(int bits, List l, boolean allowOverlapping) {
94 | StringBuilder sb = new StringBuilder();
95 | Formatter f = new Formatter(sb);
96 | String prefix = "";
97 | for (PIS p: l) {
98 | int mask = p.first;
99 | if (mask != 0 && mask == (mask & bits)) {
100 | f.format("%s%s", prefix, p.second);
101 | if (! allowOverlapping) {
102 | bits &= ~mask;
103 | }
104 | prefix = "|";
105 | }
106 | }
107 | if (bits != 0) {
108 | f.format("%s0x%x", prefix, bits);
109 | }
110 | return sb.toString();
111 | }
112 |
113 | public static class BuildItem extends Item {
114 |
115 | public BuildItem(String id, String label) {
116 | super(id, label);
117 | }
118 |
119 | public String getContents() {
120 | StringBuilder sb = new StringBuilder();
121 | Formatter f = new Formatter(sb, Locale.US);
122 | f.format("board: %s\n", Build.BOARD);
123 | f.format("bootloader: %s\n", Build.BOOTLOADER);
124 | f.format("brand: %s\n", Build.BRAND);
125 | f.format("cpu_abi: %s\n", Build.CPU_ABI);
126 | f.format("cpu_abi2: %s\n", Build.CPU_ABI2);
127 | f.format("device: %s\n", Build.DEVICE);
128 | f.format("display: %s\n", Build.DISPLAY);
129 | f.format("fingerprint: %s\n", Build.FINGERPRINT);
130 | f.format("hardware: %s\n", Build.HARDWARE);
131 | f.format("host: %s\n", Build.HOST);
132 | f.format("id: %s\n", Build.ID);
133 | f.format("manufacturer: %s\n", Build.MANUFACTURER);
134 | f.format("model: %s\n", Build.MODEL);
135 | f.format("product: %s\n", Build.PRODUCT);
136 | // f.format("radio: %s\n", Build.RADIO);
137 | f.format("serial: %s\n", Build.SERIAL);
138 | f.format("tags: %s\n", Build.TAGS);
139 | f.format("time: %s %s\n", sDateFormat.format(Build.TIME), sTimeFormat.format(Build.TIME));
140 | f.format("type: %s\n", Build.TYPE);
141 | f.format("user: %s\n", Build.USER);
142 |
143 | String s = sb.toString();
144 | Log.i("BuildItem", s);
145 | return s;
146 | }
147 | }
148 |
149 |
150 | public static class RuntimeItem extends Item {
151 |
152 | public RuntimeItem(String id, String label) {
153 | super(id, label);
154 | }
155 |
156 | public String getContents() {
157 | StringBuilder sb = new StringBuilder();
158 | Formatter f = new Formatter(sb, Locale.US);
159 | Runtime r = Runtime.getRuntime();
160 | f.format("availableProcessors: %d\n", r.availableProcessors());
161 | f.format("freeMemory: %s\n", formatFileSize(r.freeMemory()));
162 | f.format("totalMemory: %s\n", formatFileSize(r.totalMemory()));
163 | f.format("maxMemory: %s\n", formatFileSize(r.maxMemory()));
164 |
165 | return sb.toString();
166 | }
167 | }
168 |
169 | public static class ConfigurationInfoItem extends Item {
170 | private final ConfigurationInfo mConfigurationInfo;
171 |
172 | public ConfigurationInfoItem(String id, String label, ConfigurationInfo info) {
173 | super(id, label);
174 | mConfigurationInfo = info;
175 | }
176 |
177 | public String getContents() {
178 | StringBuilder sb = new StringBuilder();
179 | Formatter f = new Formatter(sb, Locale.US);
180 | ConfigurationInfo c = mConfigurationInfo;
181 | f.format("ConfigurationInfo: %s\n", c);
182 | f.format("glEsVersion: %s\n", c.getGlEsVersion());
183 | f.format("inputFeatures: %x\n", c.reqInputFeatures);
184 | f.format("keyboardType: %x\n", c.reqKeyboardType);
185 | f.format("navigation: %x\n", c.reqNavigation);
186 | f.format("touchScreen: %x\n", c.reqTouchScreen);
187 | return sb.toString();
188 | }
189 | }
190 |
191 | public static class ConfigItem extends Item {
192 | private static final String TAG = "ConfigItem";
193 | private final String mContents;
194 |
195 | public ConfigItem(String id, String label, Context context) {
196 | super(id, label);
197 | mContents = getConfig(context);
198 | Log.i(TAG, mContents);
199 | }
200 |
201 | private String getConfig(Context context) {
202 | StringBuilder sb = new StringBuilder();
203 | Configuration config = context.getResources().getConfiguration();
204 | Locale locale = config.locale;
205 | Formatter f = new Formatter(sb, locale);
206 | f.format("Config: %s\n", config);
207 | // API level 17 f.format("densityDpi = %d", config.densityDpi);
208 | f.format("fontScale: %g\n", config.fontScale);
209 | f.format("hardKeyboardHidden: %d\n", config.hardKeyboardHidden);
210 | f.format("keyboard: %d\n", config.keyboard);
211 | f.format("keyboardHidden: %d\n", config.keyboardHidden);
212 | f.format("locale: %s\n", config.locale);
213 | f.format("mcc: %d\n", config.mcc);
214 | f.format("mnc: %d\n", config.mnc);
215 | f.format("navigation: %d\n", config.navigation);
216 | f.format("navigationHidden: %d\n", config.navigationHidden);
217 | f.format("orientation: %d\n", config.orientation);
218 | f.format("screenHeightDp: %d\n", config.screenHeightDp);
219 | f.format("screenLayout: 0x%x\n", config.screenLayout);
220 | f.format("screenWidthDp: %d\n", config.screenWidthDp);
221 | f.format("smallestScreenWidthDp: %d\n", config.smallestScreenWidthDp);
222 | f.format("touchscreen: %d\n", config.touchscreen);
223 | f.format("uiMode: %s\n", formatBitmask(config.uiMode, Arrays.asList(
224 | new PIS(Configuration.UI_MODE_TYPE_UNDEFINED, "UI_MODE_TYPE_UNDEFINED"),
225 | new PIS(Configuration.UI_MODE_TYPE_NORMAL, "UI_MODE_TYPE_NORMAL"),
226 | new PIS(Configuration.UI_MODE_TYPE_DESK, "UI_MODE_TYPE_DESK"),
227 | new PIS(Configuration.UI_MODE_TYPE_CAR, "UI_MODE_TYPE_CAR"),
228 | new PIS(Configuration.UI_MODE_TYPE_TELEVISION, "UI_MODE_TYPE_TELEVISION"),
229 | new PIS(Configuration.UI_MODE_TYPE_APPLIANCE, "UI_MODE_TYPE_APPLIANCE"),
230 | new PIS(Configuration.UI_MODE_NIGHT_NO, "UI_MODE_NIGHT_NO"),
231 | new PIS(Configuration.UI_MODE_NIGHT_YES, "UI_MODE_NIGHT_YES")
232 | ), false));
233 | return sb.toString();
234 | }
235 |
236 | public String getContents() {
237 | return mContents;
238 | }
239 | }
240 |
241 | public static class OpenGLItem extends Item {
242 |
243 | public OpenGLItem(String id, String label) {
244 | super(id, label);
245 | }
246 |
247 | public String getContents() {
248 | StringBuilder sb = new StringBuilder();
249 | Formatter f = new Formatter(sb, Locale.US);
250 | String vendor = GLES10.glGetString(GLES10.GL_VENDOR);
251 | if (vendor == null) {
252 | f.format("!!! Please tap on another tab and then tap back on this tab. !!!\n\n");
253 | }
254 | f.format("vendor: %s\n", vendor);
255 | f.format("version: %s\n", GLES10.glGetString(GLES10.GL_VERSION));
256 | String extensions = GLES10.glGetString(GLES10.GL_EXTENSIONS);
257 | if (extensions == null) {
258 | extensions = "";
259 | }
260 | f.format("extensions: %s\n", extensions.replaceAll(" ", "\n"));
261 | return sb.toString();
262 | }
263 | }
264 |
265 | public static class FileInfo extends Item {
266 | private String mPath;
267 |
268 | public FileInfo(String id, String label, String path) {
269 | super(id, label);
270 | mPath = path;
271 | }
272 |
273 | public String getContents() {
274 | return mPath + ":\n" + readFile(mPath);
275 | }
276 | }
277 |
278 | public static class InputDeviceInfo extends Item {
279 | public InputDeviceInfo(String id, String label) {
280 | super(id, label);
281 | }
282 |
283 | public String getContents() {
284 | StringBuilder sb = new StringBuilder();
285 | Formatter f = new Formatter(sb, Locale.US);
286 | int[] ids = InputDevice.getDeviceIds();
287 | f.format("Device count: %d\n", ids.length);
288 | for (int i = 0; i < ids.length; i++) {
289 | int id = ids[i];
290 | InputDevice device = InputDevice.getDevice(id);
291 | f.format("#%d: id = 0x%x\n%s\n", i, id, device);
292 | }
293 | return sb.toString();
294 | }
295 | }
296 |
297 |
298 | public static class SensorsItem extends Item {
299 | final private SensorManager mManager;
300 | public SensorsItem(String id, String label, SensorManager manager) {
301 | super(id, label);
302 | mManager = manager;
303 | }
304 |
305 | public String getContents() {
306 | StringBuilder sb = new StringBuilder();
307 | Formatter f = new Formatter(sb, Locale.US);
308 | List sensors = mManager.getSensorList(Sensor.TYPE_ALL);
309 | f.format("Sensor count: %d\n", sensors.size());
310 | for (int i = 0; i < sensors.size(); i++) {
311 | Sensor s = sensors.get(i);
312 | f.format("#%d: %s\n", i, s);
313 | }
314 | return sb.toString();
315 | }
316 | }
317 |
318 | public static class BatteryItem extends Item {
319 | public BatteryItem(String id, String label) {
320 | super(id, label);
321 | }
322 |
323 | public String getContents() {
324 | StringBuilder sb = new StringBuilder();
325 | Formatter f = new Formatter(sb, Locale.US);
326 | IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
327 | Intent batteryStatus = sContext.registerReceiver(null, ifilter);
328 | f.format("present: %b\n", batteryStatus.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false));
329 | f.format("technology: %s\n", batteryStatus.getStringExtra(BatteryManager.EXTRA_TECHNOLOGY));
330 | f.format("status: %d\n", batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1));
331 | f.format("plugged: %d\n", batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1));
332 | f.format("health: %d\n", batteryStatus.getIntExtra(BatteryManager.EXTRA_HEALTH, -1));
333 | f.format("level: %d of %d\n", batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1),
334 | batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1));
335 | f.format("temperature: %d\n", batteryStatus.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, -1));
336 | f.format("voltage: %d\n", batteryStatus.getIntExtra(BatteryManager.EXTRA_VOLTAGE, -1));
337 | return sb.toString();
338 | }
339 | }
340 |
341 | public static class CamerasItem extends Item {
342 | public CamerasItem(String id, String label) {
343 | super(id, label);
344 | }
345 |
346 | public String getContents() {
347 | StringBuilder sb = new StringBuilder();
348 | Formatter f = new Formatter(sb, Locale.US);
349 | int cameraCount = Camera.getNumberOfCameras();
350 | f.format("Camera count: %d\n", cameraCount);
351 | for (int i = 0; i < cameraCount; i++) {
352 | Camera.CameraInfo info = new Camera.CameraInfo();
353 | Camera.getCameraInfo(i, info);
354 | f.format("#%d: %s\n", i, info);
355 | // f.format("canDisableShutterSound: %b\n", info.canDisableShutterSound);
356 | f.format("facing: %d\n", info.facing);
357 | f.format("orientation: %d\n", info.orientation);
358 | }
359 | return sb.toString();
360 | }
361 | }
362 |
363 | public static class DisplayMetricsItem extends Item {
364 | public DisplayMetricsItem(String id, String label) {
365 | super(id, label);
366 | }
367 |
368 | public String getContents() {
369 | StringBuilder sb = new StringBuilder();
370 | Formatter f = new Formatter(sb, Locale.US);
371 | WindowManager windowManager = (WindowManager)sContext.getSystemService(Context.WINDOW_SERVICE);
372 | Display display = windowManager.getDefaultDisplay();
373 | f.format("%s\n", display);
374 | return sb.toString();
375 | }
376 | }
377 |
378 | public static class StorageItem extends Item {
379 | public StorageItem(String id, String label) {
380 | super(id, label);
381 | }
382 |
383 | public String getContents() {
384 | StringBuilder sb = new StringBuilder();
385 | Formatter f = new Formatter(sb, Locale.US);
386 | formatStorage(f, Environment.getRootDirectory());
387 | formatStorage(f, Environment.getDataDirectory());
388 | f.format("External storage is emulated: %s\n", Environment.isExternalStorageEmulated());
389 | f.format("External storage is removable: %s\n", Environment.isExternalStorageRemovable());
390 | f.format("External storage state: %s\n", Environment.getExternalStorageState());
391 | formatStorage(f, Environment.getExternalStorageDirectory());
392 | return sb.toString();
393 | }
394 |
395 | private void formatStorage(Formatter f, File file) {
396 | String path = file.getPath();
397 | StatFs stat = new StatFs(path);
398 | long bytesAvailable = (long)stat.getBlockSize() * (long)stat.getBlockCount();
399 | f.format("path: %s size: %s\n", path, formatFileSize(bytesAvailable));
400 | }
401 | }
402 | static String readFile(String path) {
403 | BufferedReader reader;
404 | try {
405 | reader = new BufferedReader( new FileReader (path));
406 | } catch (FileNotFoundException e) {
407 | // TODO Auto-generated catch block
408 | return "Could not open " + path;
409 | }
410 | StringBuilder sb = new StringBuilder();
411 | String line;
412 | String ls = System.getProperty("line.separator");
413 |
414 | try {
415 | while( ( line = reader.readLine() ) != null ) {
416 | sb.append( line );
417 | sb.append( ls );
418 | }
419 | } catch (IOException e) {
420 | sb.append("--- io exception: " + e);
421 | }
422 |
423 | return sb.toString();
424 | }
425 |
426 |
427 | public static void init(Context context) {
428 | ITEMS.clear();
429 | ITEM_MAP.clear();
430 |
431 | sContext = context;
432 | sDateFormat = DateFormat.getDateFormat(context);
433 | sTimeFormat = DateFormat.getTimeFormat(context);
434 | int id = 1;
435 | addItem(new BuildItem(Integer.toString(id++), "Build"));
436 | addItem(new BatteryItem(Integer.toString(id++), "Battery"));
437 | addItem(new CamerasItem(Integer.toString(id++), "Cameras"));
438 | addItem(new ConfigItem(Integer.toString(id++), "Configuration", context));
439 | final ActivityManager activityManager =
440 | (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
441 | final ConfigurationInfo configurationInfo =
442 | activityManager.getDeviceConfigurationInfo();
443 | addItem(new ConfigurationInfoItem(Integer.toString(id++), "ConfigurationInfo", configurationInfo));
444 | addItem(new FileInfo(Integer.toString(id++), "CpuInfo", "/proc/cpuinfo"));
445 | addItem(new FileInfo(Integer.toString(id++), "Crypto", "/proc/crypto"));
446 | addItem(new FileInfo(Integer.toString(id++), "Devices", "/proc/devices"));
447 | addItem(new FileInfo(Integer.toString(id++), "DiskStats", "/proc/diskstats"));
448 | addItem(new DisplayMetricsItem(Integer.toString(id++), "Display"));
449 | addItem(new FileInfo(Integer.toString(id++), "Filesystems", "/proc/filesystems"));
450 | addItem(new InputDeviceInfo(Integer.toString(id++), "Input Devices"));
451 | addItem(new FileInfo(Integer.toString(id++), "Kernel Version", "/proc/version"));
452 | addItem(new FileInfo(Integer.toString(id++), "LoadAvg", "/proc/loadavg"));
453 | addItem(new FileInfo(Integer.toString(id++), "Memory", "/proc/meminfo"));
454 | addItem(new FileInfo(Integer.toString(id++), "Modules", "/proc/modules"));
455 | addItem(new OpenGLItem(Integer.toString(id++), "OpenGL"));
456 | addItem(new RuntimeItem(Integer.toString(id++), "Runtime"));
457 | addItem(new SensorsItem(Integer.toString(id++), "Sensors", (SensorManager) context.getSystemService(Context.SENSOR_SERVICE)));
458 | addItem(new StorageItem(Integer.toString(id++), "Storage"));
459 | addItem(new FileInfo(Integer.toString(id++), "Uptime", "/proc/uptime"));
460 | }
461 |
462 | private static String formatFileSize(long n) {
463 | return android.text.format.Formatter.formatFileSize(sContext, n);
464 | }
465 | }
466 |
--------------------------------------------------------------------------------