Merge branch 'master' into honeycomb-release
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
130
pdk/docs/compatibility/cts-development.jd
Normal file
130
pdk/docs/compatibility/cts-development.jd
Normal 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>
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -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">
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
5
samples/ApiDemos/res/menu/camera_menu.xml
Normal file
5
samples/ApiDemos/res/menu/camera_menu.xml
Normal 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>
|
||||
@@ -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 -->
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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!");
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user