Merge branch 'master' into honeycomb-release

This commit is contained in:
The Android Automerger
2010-11-30 07:22:29 -08:00
12 changed files with 436 additions and 20 deletions

View File

@@ -146,13 +146,13 @@ development/samples/source.properties samples/${PLATFORM_NAME}/source.pro
# PLEASE KEEP THE SAMPLES IN ALPHABETICAL ORDER.
#
development/samples/AccessibilityService samples/${PLATFORM_NAME}/AccessibilityService
development/samples/AccelerometerPlay samples/${PLATFORM_NAME}/AccelerometerPlay
development/samples/ApiDemos samples/${PLATFORM_NAME}/ApiDemos
development/samples/BackupRestore samples/${PLATFORM_NAME}/BackupRestore
development/samples/BluetoothChat samples/${PLATFORM_NAME}/BluetoothChat
development/samples/ContactManager samples/${PLATFORM_NAME}/ContactManager
development/samples/CrossCompatibility samples/${PLATFORM_NAME}/CrossCompatibility
development/samples/CubeLiveWallpaper samples/${PLATFORM_NAME}/CubeLiveWallpaper
development/samples/HeavyWeight samples/${PLATFORM_NAME}/HeavyWeight
development/samples/Home samples/${PLATFORM_NAME}/Home
development/samples/JetBoy samples/${PLATFORM_NAME}/JetBoy
development/samples/LunarLander samples/${PLATFORM_NAME}/LunarLander

View File

@@ -9,6 +9,7 @@ function nothing() {}
<li><a href="<?cs var:toroot ?>compatibility/overview.html">Compatibility Overview</a></li>
<li><a href="<?cs var:toroot ?>compatibility/android-2.2-cdd.pdf">Current CDD</a></li>
<li><a href="<?cs var:toroot ?>compatibility/cts-intro.html">CTS Introduction</a></li>
<li><a href="<?cs var:toroot ?>compatibility/cts-development.html">CTS Development</a></li>
</ul></li>
<li><h2>More Information</h2><ul>

View File

@@ -0,0 +1,130 @@
page.title=CTS Development
doc.type=compatibility
@jd:body
<h3>Initializing Your Repo Client</h3>
<p>Follow the
<a href="{@docRoot}source/download.html">instructions</a>
to get and build the Android source code but specify "-b froyo"
when issuing the "repo init" command. This assures that your CTS
changes will be included in the next CTS release and beyond.</p>
<h3>Setting Up Eclipse</h3>
<p>Follow the
<a href="{@docRoot}source/using-eclipse.html">instructions</a>
to setup Eclipse but execute the following command to generate the
.classpath file rather than copying the one from the development
project:</p>
<pre>
cd /path/to/android/root
./cts/development/ide/eclipse/genclasspath.sh > .classpath
chmod u+w .classpath
</pre>
<p>This .classpath file will contain both the Android framework
packages and the CTS packages.</p>
<h3>Building and Running CTS</h3>
<p>Execute the following commands to build CTS and start the interactive
CTS console:</p>
<pre>
cd /path/to/android/root
make cts
cts
</pre>
<p>Provide arguments to CTS to immediately start executing a test:</p>
<pre>
cts start --plan CTS -p android.os.cts.BuildVersionTest
</pre>
<h3>Writing CTS Tests</h3>
<p>CTS tests use JUnit and the Android testing APIs. Review the
<a href="http://d.android.com/guide/topics/testing/testing_android.html">Testing
and Instrumentation</a> tutorial while perusing the existing tests under the
"cts/tests/tests" directory. You will see that CTS tests mostly follow the same
conventions used in other Android tests.</p>
<p>Since CTS runs across many production devices, the tests must follow
these rules:</p>
<ul>
<li>Must take into account varying screen sizes, orientations, and
keyboard layouts.</li>
<li>Only use public API methods. In other words, avoid all classes,
methods, and fields that are annotated with the "hide" annotation.</li>
<li>Avoid relying upon particular view layouts or depend on the
dimensions of assets that may not be on some device.</li>
<li>Don't rely upon root privileges.</li>
</ul>
<h4>Test Naming and Location</h4>
<p>Most CTS test cases target a specific class in the Android API. These tests
have Java package names with a "cts" suffix like "android.view.cts" and class
names with the "Test" suffix like "ViewTest." Each test case consists of
multiple tests, where each test usually exercises a particular API method of
the API class being tested. Each test is annotated with a @TestTargetNew
annotation to indicate what API method is being exercised. These tests are
arranged in a directory structure where tests are grouped into different
categories like "widgets" and "views."</p>
<p>For example, the CTS test for "android.widget.TextView" is
"android.widget.cts.TextVietTest" found under the
"cts/tests/tests/widget/src/android/widget/cts" directory with its
Java package name as "android.widget.cts" and its class name as
"TextViewTest." The "TextViewTest" class has a test called "testSetText"
that exercises the "setText" method and a test named "testSetSingleLine" that
calls the "setSingleLine" method. Each of those tests have @TestTargetNew
annotations indicating what they cover.</p>
<p>Some CTS tests do not directly correspond to an API class but are placed in
the most related package possible. For instance, the CTS test,
"android.net.cts.ListeningPortsTest," is in the "android.net.cts," because it
is network related even though there is no "android.net.ListeningPorts" class.
Thus, use your best judgement when adding new tests and refer to other tests
as examples.</p>
<h4>New Test Packages</h4>
<p>When adding new tests, there may not be an existing directory to place your
test. In that case, refer to the example under "cts/tests/tests/example" and
create a new directory. Furthermore, make sure to add your new package's
module name from its Android.mk to "CTS_COVERAGE_TEST_CASE_LIST" in
"cts/CtsTestCaseList.mk." This Makefile is used by "build/core/tasks/cts.mk"
to glue all the tests together to create the final CTS package.</p>
<h4>Test Stubs and Utilities</h4>
<p>Some tests use additional infrastructure like separate activities
and various utilities to perform tests. These are located under the
"cts/tests/src" directory. These stubs aren't separated into separate test
APKs like the tests, so the "cts/tests/src" directory does not have additional
top level directories like "widget" or "view." Follow the same principle of
putting new classes into a package with a name that correlates to the purpose
of your new class. For instance, a stub activity used for testing OpenGL like
"GLSurfaceViewStubActivity" belongs in the "android.opengl.cts" package under
the "cts/tests/src/android/opengl" directory.</p>
<h3>Other Tasks</h3>
<p>Besides adding new tests there are other ways to contribute to CTS:</p>
<ul>
<li>Fix or remove tests annotated with BrokenTest and KnownFailure.</li>
</ul>
<h3>Submitting Your Changes</h3>
<p>Follow the
<a href="{@docRoot}source/submit-patches.html">Android
contributors' workflow</a> to contribute changes to CTS. A reviewer
will be assigned to your change, and your change should be reviewed shortly!</p>

View File

@@ -29,6 +29,9 @@
<Button android:id="@+id/two_buttons2"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:text="@string/alert_dialog_two_buttons2"/>
<Button android:id="@+id/two_buttons2ultra"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:text="@string/alert_dialog_two_buttons2ultra"/>
<Button android:id="@+id/select_button"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:text="@string/alert_dialog_select_button"/>

View File

@@ -158,6 +158,20 @@
</LinearLayout>
<LinearLayout android:orientation="horizontal" android:gravity="center"
android:layout_width="match_parent" android:layout_height="wrap_content">
<TextView android:id="@+id/password_expiration_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button android:id="@+id/update_expiration_status_button"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android_layout_gravity="east|center_vertical"
android:text="@string/update_expiration_status_label" />
</LinearLayout>
<LinearLayout android:orientation="horizontal" android:gravity="center"
android:layout_width="match_parent" android:layout_height="wrap_content">

View File

@@ -18,7 +18,7 @@
android:icon="@android:drawable/ic_menu_search"
android:title="@string/action_bar_search"
android:showAsAction="ifRoom"
android:onClick="onSearch" />
android:actionViewClass="android.widget.SearchView" />
<item android:id="@+id/action_add"
android:icon="@android:drawable/ic_menu_add"
android:title="@string/action_bar_add" />
@@ -30,15 +30,19 @@
android:icon="@android:drawable/ic_menu_share"
android:title="@string/action_bar_share"
android:showAsAction="ifRoom" />
<item android:id="@+id/action_zoom"
android:icon="@android:drawable/ic_menu_zoom"
android:title="@string/action_bar_zoom"
<item android:id="@+id/action_sort"
android:icon="@android:drawable/ic_menu_sort_by_size"
android:title="@string/action_bar_sort"
android:showAsAction="ifRoom">
<menu>
<item android:id="@+id/action_save"
android:icon="@android:drawable/ic_menu_save"
android:title="@string/action_bar_save"
android:showAsAction="ifRoom" />
<item android:id="@+id/action_sort_size"
android:icon="@android:drawable/ic_menu_sort_by_size"
android:title="@string/action_bar_sort_size"
android:onClick="onSort" />
<item android:id="@+id/action_sort_alpha"
android:icon="@android:drawable/ic_menu_sort_alphabetically"
android:title="@string/action_bar_sort_alpha"
android:onClick="onSort" />
</menu>
</item>
</menu>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/switch_cam"
android:title="@string/switch_cam" />
</menu>

View File

@@ -370,6 +370,7 @@
<string name="activity_alert_dialog">App/Dialog</string>
<string name="alert_dialog_two_buttons">OK Cancel dialog with a message</string>
<string name="alert_dialog_two_buttons2">OK Cancel dialog with a long message</string>
<string name="alert_dialog_two_buttons2ultra">OK Cancel dialog with ultra long message</string>
<string name="alert_dialog_select_button">List dialog</string>
<string name="alert_dialog_single_choice">Single choice list</string>
<string name="alert_dialog_multi_choice">Repeat alarm</string>
@@ -391,6 +392,44 @@
kipg naar mixent phona. Cak pwico siructiun
ruous nust apoply tyu cak Uhex sisulutiun munityuw uw dseg
</string>
<string name="alert_dialog_two_buttons2ultra_msg">
Plloaso mako nuto siwuf cakso dodtos anr koop a
cupy uf cak vux noaw yerw phuno. Whag schengos, uf efed, quiel
ba mada su otrenzr.\n\nSwipontgwook proudgs hus yag su ba dagarmidad.
Plasa maku noga wipont trenzsa schengos ent kaap zux comy.\n\nWipont trenz
kipg naar mixent phona. Cak pwico siructiun
ruous nust apoply tyu cak Uhex sisulutiun munityuw uw dseg\n\n
Plloaso mako nuto siwuf cakso dodtos anr koop a
cupy uf cak vux noaw yerw phuno. Whag schengos, uf efed, quiel
ba mada su otrenzr.\n\nSwipontgwook proudgs hus yag su ba dagarmidad.
Plasa maku noga wipont trenzsa schengos ent kaap zux comy.\n\nWipont trenz
kipg naar mixent phona. Cak pwico siructiun
ruous nust apoply tyu cak Uhex sisulutiun munityuw uw dseg\n\n
Plloaso mako nuto siwuf cakso dodtos anr koop a
cupy uf cak vux noaw yerw phuno. Whag schengos, uf efed, quiel
ba mada su otrenzr.\n\nSwipontgwook proudgs hus yag su ba dagarmidad.
Plasa maku noga wipont trenzsa schengos ent kaap zux comy.\n\nWipont trenz
kipg naar mixent phona. Cak pwico siructiun
ruous nust apoply tyu cak Uhex sisulutiun munityuw uw dseg\n\n
Plloaso mako nuto siwuf cakso dodtos anr koop a
cupy uf cak vux noaw yerw phuno. Whag schengos, uf efed, quiel
ba mada su otrenzr.\n\nSwipontgwook proudgs hus yag su ba dagarmidad.
Plasa maku noga wipont trenzsa schengos ent kaap zux comy.\n\nWipont trenz
kipg naar mixent phona. Cak pwico siructiun
ruous nust apoply tyu cak Uhex sisulutiun munityuw uw dseg\n\n
Plloaso mako nuto siwuf cakso dodtos anr koop a
cupy uf cak vux noaw yerw phuno. Whag schengos, uf efed, quiel
ba mada su otrenzr.\n\nSwipontgwook proudgs hus yag su ba dagarmidad.
Plasa maku noga wipont trenzsa schengos ent kaap zux comy.\n\nWipont trenz
kipg naar mixent phona. Cak pwico siructiun
ruous nust apoply tyu cak Uhex sisulutiun munityuw uw dseg\n\n
Plloaso mako nuto siwuf cakso dodtos anr koop a
cupy uf cak vux noaw yerw phuno. Whag schengos, uf efed, quiel
ba mada su otrenzr.\n\nSwipontgwook proudgs hus yag su ba dagarmidad.
Plasa maku noga wipont trenzsa schengos ent kaap zux comy.\n\nWipont trenz
kipg naar mixent phona. Cak pwico siructiun
ruous nust apoply tyu cak Uhex sisulutiun munityuw uw dseg\n\n
</string>
<string name="alert_dialog_ok">OK</string>
<string name="alert_dialog_hide">Hide</string>
<string name="alert_dialog_something">Something</string>
@@ -551,6 +590,7 @@
<string name="password_history_length_hint">Password History Length</string>
<string name="password_expiration_hint">Password Expiration Timeout (minutes) </string>
<string name="update_expiration_label">Update</string>
<string name="update_expiration_status_label">Update Status</string>
<string name="set_password">Set Password</string>
<string name="password_hint">Password</string>
<string name="reset_password">Reset Password</string>
@@ -584,8 +624,9 @@
<string name="action_bar_add">Add</string>
<string name="action_bar_edit">Edit</string>
<string name="action_bar_share">Share</string>
<string name="action_bar_zoom">Zoom</string>
<string name="action_bar_save">Save</string>
<string name="action_bar_sort">Sort</string>
<string name="action_bar_sort_alpha">Alphabetically</string>
<string name="action_bar_sort_size">By size</string>
<string name="action_bar_display_options">App/Action Bar/Display Options</string>
<string name="toggle_home_as_up">DISPLAY_HOME_AS_UP</string>
@@ -611,6 +652,8 @@
<string name="hide_me">Hide Me!</string>
<string name="density_title">Density: Unknown Screen</string>
<string name="camera_alert">Device has only one camera!</string>
<string name="switch_cam">Switch Camera</string>
<!-- ============================ -->
<!-- media examples strings -->

View File

@@ -16,9 +16,14 @@
package com.example.android.apis.app;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.SearchView;
import android.widget.SearchView.OnQueryChangeListener;
import android.widget.TextView;
import android.widget.Toast;
import com.example.android.apis.R;
@@ -29,14 +34,35 @@ import com.example.android.apis.R;
* menu data itself. If you'd like to see how these things work under the hood, see
* ActionBarMechanics.
*/
public class ActionBarUsage extends Activity {
public class ActionBarUsage extends Activity implements OnQueryChangeListener {
TextView mSearchText;
int mSortMode = -1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSearchText = new TextView(this);
setContentView(mSearchText);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.actions, menu);
SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
searchView.setOnQueryChangeListener(this);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
if (mSortMode != -1) {
Drawable icon = menu.findItem(mSortMode).getIcon();
menu.findItem(R.id.action_sort).setIcon(icon);
}
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Toast.makeText(this, "Selected Item: " + item.getTitle(), Toast.LENGTH_SHORT).show();
@@ -46,7 +72,24 @@ public class ActionBarUsage extends Activity {
// This method is specified as an onClick handler in the menu xml and will
// take precedence over the Activity's onOptionsItemSelected method.
// See res/menu/actions.xml for more info.
public void onSearch(MenuItem item) {
Toast.makeText(this, "Searching...", Toast.LENGTH_SHORT).show();
public void onSort(MenuItem item) {
mSortMode = item.getItemId();
// Request a call to onPrepareOptionsMenu so we can change the sort icon
invalidateOptionsMenu();
}
// The following callbacks are called for the SearchView.OnQueryChangeListener
// For more about using SearchView, see src/.../view/SearchView1.java and SearchView2.java
@Override
public boolean onQueryTextChanged(String newText) {
newText = newText.isEmpty() ? "" : "Query so far: " + newText;
mSearchText.setText(newText);
return true;
}
@Override
public boolean onSubmitQuery(String query) {
Toast.makeText(this, "Searching for: " + query + "...", Toast.LENGTH_SHORT).show();
return true;
}
}

View File

@@ -64,6 +64,7 @@ public class AlertDialogSamples extends Activity {
private static final int DIALOG_MULTIPLE_CHOICE = 6;
private static final int DIALOG_TEXT_ENTRY = 7;
private static final int DIALOG_MULTIPLE_CHOICE_CURSOR = 8;
private static final int DIALOG_YES_NO_ULTRA_LONG_MESSAGE = 9;
private static final int MAX_PROGRESS = 100;
@@ -115,6 +116,30 @@ public class AlertDialogSamples extends Activity {
}
})
.create();
case DIALOG_YES_NO_ULTRA_LONG_MESSAGE:
return new AlertDialog.Builder(AlertDialogSamples.this)
.setIcon(R.drawable.alert_dialog_icon)
.setTitle(R.string.alert_dialog_two_buttons_msg)
.setMessage(R.string.alert_dialog_two_buttons2ultra_msg)
.setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
/* User clicked OK so do some stuff */
}
})
.setNeutralButton(R.string.alert_dialog_something, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
/* User clicked Something so do some stuff */
}
})
.setNegativeButton(R.string.alert_dialog_cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
/* User clicked Cancel so do some stuff */
}
})
.create();
case DIALOG_LIST:
return new AlertDialog.Builder(AlertDialogSamples.this)
.setTitle(R.string.select_dialog)
@@ -277,6 +302,15 @@ public class AlertDialogSamples extends Activity {
});
/* Display an ultra long text message with yes/no buttons and handle each message as well as the cancel action */
Button twoButtons2UltraTitle = (Button) findViewById(R.id.two_buttons2ultra);
twoButtons2UltraTitle.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
showDialog(DIALOG_YES_NO_ULTRA_LONG_MESSAGE);
}
});
/* Display a list of items */
Button selectButton = (Button) findViewById(R.id.select_button);
selectButton.setOnClickListener(new OnClickListener() {

View File

@@ -40,6 +40,7 @@ import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import java.net.InetSocketAddress;
@@ -170,7 +171,6 @@ public class DeviceAdminSample extends DeviceAdminReceiver {
EditText mPasswordMinimumSymbols;
EditText mPasswordMinimumNonLetter;
EditText mPasswordHistoryLength;
EditText mPasswordExpirationTimeout;
Button mSetPasswordButton;
EditText mPassword;
@@ -190,7 +190,10 @@ public class DeviceAdminSample extends DeviceAdminReceiver {
EditText mProxyList;
Button mProxyButton;
private EditText mPasswordExpirationTimeout;
private Button mPasswordExpirationButton;
private TextView mPasswordExpirationStatus;
private Button mPasswordExpirationStatusButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -333,12 +336,21 @@ public class DeviceAdminSample extends DeviceAdminReceiver {
mPasswordExpirationButton = (Button) findViewById(R.id.update_expiration_button);
mPasswordExpirationButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
long expiration;
try {
setPasswordExpiration(
Long.parseLong(mPasswordExpirationTimeout.getText().toString()));
} catch (NumberFormatException nfe) {
}
updatePasswordExpirationStatus();
}
});
mPasswordExpirationStatus = (TextView) findViewById(R.id.password_expiration_status);
mPasswordExpirationStatusButton =
(Button) findViewById(R.id.update_expiration_status_button);
mPasswordExpirationStatusButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
updatePasswordExpirationStatus();
}
});
@@ -458,6 +470,41 @@ public class DeviceAdminSample extends DeviceAdminReceiver {
mMaxFailedPw.setText(Integer.toString(maxFailedPw));
}
void updatePasswordExpirationStatus() {
boolean active = mDPM.isAdminActive(mDeviceAdminSample);
String statusText;
if (active) {
long now = System.currentTimeMillis();
// We'll query the DevicePolicyManager twice - first for the expiration values
// set by the sample app, and later, for the system values (which may be different
// if there is another administrator active.)
long expirationDate = mDPM.getPasswordExpiration(mDeviceAdminSample);
long mSecUntilExpiration = expirationDate - now;
if (mSecUntilExpiration >= 0) {
statusText = "Expiration in " + countdownString(mSecUntilExpiration);
} else {
statusText = "Expired " + countdownString(-mSecUntilExpiration) + " ago";
}
// expirationTimeout is the cycle time between required password refresh
long expirationTimeout = mDPM.getPasswordExpirationTimeout(mDeviceAdminSample);
statusText += " / timeout period " + countdownString(expirationTimeout);
// Now report the aggregate (global) expiration time
statusText += " / Aggregate ";
expirationDate = mDPM.getPasswordExpiration(null);
mSecUntilExpiration = expirationDate - now;
if (mSecUntilExpiration >= 0) {
statusText += "expiration in " + countdownString(mSecUntilExpiration);
} else {
statusText += "expired " + countdownString(-mSecUntilExpiration) + " ago";
}
} else {
statusText = "<inactive>";
}
mPasswordExpirationStatus.setText(statusText);
}
void updatePolicies() {
SharedPreferences prefs = getSamplePreferences(this);
final int pwQuality = prefs.getInt(PREF_PASSWORD_QUALITY,
@@ -569,6 +616,7 @@ public class DeviceAdminSample extends DeviceAdminReceiver {
protected void onResume() {
super.onResume();
updateButtonStates();
updatePasswordExpirationStatus();
}
@Override
@@ -615,7 +663,7 @@ public class DeviceAdminSample extends DeviceAdminReceiver {
private OnClickListener mResetPasswordListener = new OnClickListener() {
public void onClick(View v) {
if (mAM.isUserAMonkey()) {
if (ActivityManager.isUserAMonkey()) {
// Don't trust monkeys to do the right thing!
AlertDialog.Builder builder = new AlertDialog.Builder(Controller.this);
builder.setMessage("You can't reset my password because you are a monkey!");
@@ -633,7 +681,7 @@ public class DeviceAdminSample extends DeviceAdminReceiver {
private OnClickListener mForceLockListener = new OnClickListener() {
public void onClick(View v) {
if (mAM.isUserAMonkey()) {
if (ActivityManager.isUserAMonkey()) {
// Don't trust monkeys to do the right thing!
AlertDialog.Builder builder = new AlertDialog.Builder(Controller.this);
builder.setMessage("You can't lock my screen because you are a monkey!");
@@ -650,7 +698,7 @@ public class DeviceAdminSample extends DeviceAdminReceiver {
private OnClickListener mWipeDataListener = new OnClickListener() {
public void onClick(final View v) {
if (mAM.isUserAMonkey()) {
if (ActivityManager.isUserAMonkey()) {
// Don't trust monkeys to do the right thing!
AlertDialog.Builder builder = new AlertDialog.Builder(Controller.this);
builder.setMessage("You can't wipe my data because you are a monkey!");
@@ -694,7 +742,7 @@ public class DeviceAdminSample extends DeviceAdminReceiver {
private OnClickListener mSetTimeoutListener = new OnClickListener() {
public void onClick(View v) {
if (mAM.isUserAMonkey()) {
if (ActivityManager.isUserAMonkey()) {
// Don't trust monkeys to do the right thing!
AlertDialog.Builder builder = new AlertDialog.Builder(Controller.this);
builder.setMessage("You can't lock my screen because you are a monkey!");

View File

@@ -17,11 +17,16 @@
package com.example.android.apis.graphics;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
@@ -32,11 +37,20 @@ import android.view.WindowManager;
import java.io.IOException;
import java.util.List;
// Need the following import to get access to the app resources, since this
// class is in a sub-package.
import com.example.android.apis.R;
// ----------------------------------------------------------------------
public class CameraPreview extends Activity {
private Preview mPreview;
Camera mCamera;
int numberOfCameras;
int cameraCurrentlyLocked;
// The first rear facing camera
int defaultCameraId;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -50,13 +64,27 @@ public class CameraPreview extends Activity {
// and set it as the content of our activity.
mPreview = new Preview(this);
setContentView(mPreview);
// Find the total number of cameras available
numberOfCameras = Camera.getNumberOfCameras();
// Find the ID of the default camera
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
defaultCameraId = i;
}
}
}
@Override
protected void onResume() {
super.onResume();
// Open the default i.e. the first rear facing camera.
mCamera = Camera.open();
cameraCurrentlyLocked = defaultCameraId;
mPreview.setCamera(mCamera);
}
@@ -72,6 +100,55 @@ public class CameraPreview extends Activity {
mCamera = null;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate our menu which can gather user input for switching camera
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.camera_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.switch_cam:
// check for availability of multiple cameras
if (numberOfCameras == 1) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(this.getString(R.string.camera_alert))
.setNeutralButton("Close", null);
AlertDialog alert = builder.create();
alert.show();
return true;
}
// OK, we have multiple cameras.
// Release this camera -> cameraCurrentlyLocked
if (mCamera != null) {
mCamera.stopPreview();
mPreview.setCamera(null);
mCamera.release();
mCamera = null;
}
// Acquire the next camera and request Preview to reconfigure
// parameters.
mCamera = Camera
.open((cameraCurrentlyLocked + 1) % numberOfCameras);
cameraCurrentlyLocked = (cameraCurrentlyLocked + 1)
% numberOfCameras;
mPreview.switchCamera(mCamera);
// Start the preview
mCamera.startPreview();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
// ----------------------------------------------------------------------
@@ -111,6 +188,20 @@ class Preview extends ViewGroup implements SurfaceHolder.Callback {
}
}
public void switchCamera(Camera camera) {
setCamera(camera);
try {
camera.setPreviewDisplay(mHolder);
} catch (IOException exception) {
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
requestLayout();
camera.setParameters(parameters);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// We purposely disregard child measurements because act as a