Merge "Fix issues in LayoutAnimationsHideShow demo."
diff --git a/samples/ApiDemos/AndroidManifest.xml b/samples/ApiDemos/AndroidManifest.xml
index 7b3fabd..a26bb88 100644
--- a/samples/ApiDemos/AndroidManifest.xml
+++ b/samples/ApiDemos/AndroidManifest.xml
@@ -984,6 +984,18 @@
</intent-filter>
</activity>
+ <activity android:name=".content.InstallApk" android:label="@string/activity_install_apk"
+ android:enabled="@bool/atLeastHoneycombMR2">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <provider android:name=".content.FileProvider"
+ android:authorities="com.example.android.apis.content.FileProvider"
+ android:enabled="@bool/atLeastHoneycombMR2" />
+
<!-- ************************************* -->
<!-- OS PACKAGE SAMPLES -->
<!-- ************************************* -->
diff --git a/samples/ApiDemos/assets/HelloActivity.apk b/samples/ApiDemos/assets/HelloActivity.apk
new file mode 100644
index 0000000..4e4b487
--- /dev/null
+++ b/samples/ApiDemos/assets/HelloActivity.apk
Binary files differ
diff --git a/samples/ApiDemos/res/layout/install_apk.xml b/samples/ApiDemos/res/layout/install_apk.xml
new file mode 100644
index 0000000..1482d2c
--- /dev/null
+++ b/samples/ApiDemos/res/layout/install_apk.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Demonstrates starting and stopping a local service.
+ See corresponding Java code com.android.sdk.app.LocalSerice.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="match_parent" android:layout_height="match_parent">
+
+ <TextView
+ android:layout_width="match_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="Demonstrates using the INSTALL_PACKAGE Intent to install an application."/>
+
+ <Button android:id="@+id/unknown_source"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="Unknown Source">
+ </Button>
+
+ <Button android:id="@+id/my_source"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="My Source">
+ </Button>
+
+ <Button android:id="@+id/replace"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="Replace">
+ </Button>
+
+ <Button android:id="@+id/uninstall"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="Uninstall">
+ </Button>
+
+ <Button android:id="@+id/uninstall_result"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="Uninstall w/Result">
+ </Button>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/searchview_actionbar.xml b/samples/ApiDemos/res/layout/searchview_actionbar.xml
index 37736cd..2ed62d4 100644
--- a/samples/ApiDemos/res/layout/searchview_actionbar.xml
+++ b/samples/ApiDemos/res/layout/searchview_actionbar.xml
@@ -19,22 +19,6 @@
android:layout_height="match_parent"
android:orientation="vertical">
- <Button
- android:id="@+id/open_button"
- android:text="@string/open_search"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal"
- />
-
- <Button
- android:id="@+id/close_button"
- android:text="@string/close_search"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal"
- />
-
<TextView
android:id="@+id/status_text"
android:layout_width="match_parent"
diff --git a/samples/ApiDemos/res/values/strings.xml b/samples/ApiDemos/res/values/strings.xml
index ddf7e39..45d4755 100644
--- a/samples/ApiDemos/res/values/strings.xml
+++ b/samples/ApiDemos/res/values/strings.xml
@@ -363,6 +363,8 @@
<string name="pick_phone">Pick a Phone</string>
<string name="pick_address">Pick an Address</string>
+ <string name="activity_install_apk">Content/Packages/Install Apk</string>
+
<!-- ============================== -->
<!-- app/intents examples strings -->
<!-- ============================== -->
diff --git a/samples/ApiDemos/src/com/example/android/apis/content/FileProvider.java b/samples/ApiDemos/src/com/example/android/apis/content/FileProvider.java
new file mode 100644
index 0000000..156625a
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/content/FileProvider.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.content;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.ContentProvider.PipeDataWriter;
+import android.content.res.AssetFileDescriptor;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+/**
+ * A very simple content provider that can serve arbitrary asset files from
+ * our .apk.
+ */
+public class FileProvider extends ContentProvider
+ implements PipeDataWriter<InputStream> {
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ // Don't support queries.
+ return null;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ // Don't support inserts.
+ return null;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ // Don't support deletes.
+ return 0;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ // Don't support updates.
+ return 0;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ // For this sample, assume all files are .apks.
+ return "application/vnd.android.package-archive";
+ }
+
+ @Override
+ public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException {
+ // Try to open an asset with the given name.
+ try {
+ InputStream is = getContext().getAssets().open(uri.getPath());
+ // Start a new thread that pipes the stream data back to the caller.
+ return new AssetFileDescriptor(
+ openPipeHelper(uri, null, null, is, this), 0,
+ AssetFileDescriptor.UNKNOWN_LENGTH);
+ } catch (IOException e) {
+ FileNotFoundException fnf = new FileNotFoundException("Unable to open " + uri);
+ throw fnf;
+ }
+ }
+
+ @Override
+ public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String mimeType,
+ Bundle opts, InputStream args) {
+ // Transfer data from the asset to the pipe the client is reading.
+ byte[] buffer = new byte[8192];
+ int n;
+ FileOutputStream fout = new FileOutputStream(output.getFileDescriptor());
+ try {
+ while ((n=args.read(buffer)) >= 0) {
+ fout.write(buffer, 0, n);
+ }
+ } catch (IOException e) {
+ Log.i("InstallApk", "Failed transferring", e);
+ } finally {
+ try {
+ args.close();
+ } catch (IOException e) {
+ }
+ try {
+ fout.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/content/InstallApk.java b/samples/ApiDemos/src/com/example/android/apis/content/InstallApk.java
new file mode 100644
index 0000000..9036ee0
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/content/InstallApk.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.content;
+
+// 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;
+
+import android.app.Activity;
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ContentProvider.PipeDataWriter;
+import android.content.res.AssetFileDescriptor;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+
+/**
+ * Demonstration of styled text resources.
+ */
+public class InstallApk extends Activity {
+ static final int REQUEST_INSTALL = 1;
+ static final int REQUEST_UNINSTALL = 2;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.install_apk);
+
+ // Watch for button clicks.
+ Button button = (Button)findViewById(R.id.unknown_source);
+ button.setOnClickListener(mUnknownSourceListener);
+ button = (Button)findViewById(R.id.my_source);
+ button.setOnClickListener(mMySourceListener);
+ button = (Button)findViewById(R.id.replace);
+ button.setOnClickListener(mReplaceListener);
+ button = (Button)findViewById(R.id.uninstall);
+ button.setOnClickListener(mUninstallListener);
+ button = (Button)findViewById(R.id.uninstall_result);
+ button.setOnClickListener(mUninstallResultListener);
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+ if (requestCode == REQUEST_INSTALL) {
+ if (resultCode == Activity.RESULT_OK) {
+ Toast.makeText(this, "Install succeeded!", Toast.LENGTH_SHORT).show();
+ } else if (resultCode == Activity.RESULT_CANCELED) {
+ Toast.makeText(this, "Install canceled!", Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(this, "Install Failed!", Toast.LENGTH_SHORT).show();
+ }
+ } else if (requestCode == REQUEST_UNINSTALL) {
+ if (resultCode == Activity.RESULT_OK) {
+ Toast.makeText(this, "Uninstall succeeded!", Toast.LENGTH_SHORT).show();
+ } else if (resultCode == Activity.RESULT_CANCELED) {
+ Toast.makeText(this, "Uninstall canceled!", Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(this, "Uninstall Failed!", Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
+
+ private OnClickListener mUnknownSourceListener = new OnClickListener() {
+ public void onClick(View v) {
+ Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
+ intent.setData(Uri.fromFile(prepareApk("HelloActivity.apk")));
+ startActivity(intent);
+ }
+ };
+
+ private OnClickListener mMySourceListener = new OnClickListener() {
+ public void onClick(View v) {
+ Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
+ intent.setData(Uri.fromFile(prepareApk("HelloActivity.apk")));
+ intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
+ intent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
+ intent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME,
+ getApplicationInfo().packageName);
+ startActivityForResult(intent, REQUEST_INSTALL);
+ }
+ };
+
+ private OnClickListener mReplaceListener = new OnClickListener() {
+ public void onClick(View v) {
+ Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
+ intent.setData(Uri.fromFile(prepareApk("HelloActivity.apk")));
+ intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
+ intent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
+ intent.putExtra(Intent.EXTRA_ALLOW_REPLACE, true);
+ intent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME,
+ getApplicationInfo().packageName);
+ startActivityForResult(intent, REQUEST_INSTALL);
+ }
+ };
+
+ private OnClickListener mUninstallListener = new OnClickListener() {
+ public void onClick(View v) {
+ Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE);
+ intent.setData(Uri.parse(
+ "package:com.example.android.helloactivity"));
+ startActivity(intent);
+ }
+ };
+
+ private OnClickListener mUninstallResultListener = new OnClickListener() {
+ public void onClick(View v) {
+ Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE);
+ intent.setData(Uri.parse(
+ "package:com.example.android.helloactivity"));
+ intent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
+ startActivityForResult(intent, REQUEST_UNINSTALL);
+ }
+ };
+
+ private File prepareApk(String assetName) {
+ // Copy the given asset out into a file so that it can be installed.
+ // Returns the path to the file.
+ byte[] buffer = new byte[8192];
+ InputStream is = null;
+ FileOutputStream fout = null;
+ try {
+ is = getAssets().open(assetName);
+ fout = openFileOutput("tmp.apk", Context.MODE_WORLD_READABLE);
+ int n;
+ while ((n=is.read(buffer)) >= 0) {
+ fout.write(buffer, 0, n);
+ }
+ } catch (IOException e) {
+ Log.i("InstallApk", "Failed transferring", e);
+ } finally {
+ try {
+ if (is != null) {
+ is.close();
+ }
+ } catch (IOException e) {
+ }
+ try {
+ if (fout != null) {
+ fout.close();
+ }
+ } catch (IOException e) {
+ }
+ }
+
+ return getFileStreamPath("tmp.apk");
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/SearchViewActionBar.java b/samples/ApiDemos/src/com/example/android/apis/view/SearchViewActionBar.java
index 8ffa3b9..bffeb96 100644
--- a/samples/ApiDemos/src/com/example/android/apis/view/SearchViewActionBar.java
+++ b/samples/ApiDemos/src/com/example/android/apis/view/SearchViewActionBar.java
@@ -39,12 +39,9 @@
* This demonstrates the usage of SearchView in an ActionBar as a menu item.
* It sets a SearchableInfo on the SearchView for suggestions and submitting queries to.
*/
-public class SearchViewActionBar extends Activity implements SearchView.OnQueryTextListener,
- SearchView.OnCloseListener, Button.OnClickListener {
+public class SearchViewActionBar extends Activity implements SearchView.OnQueryTextListener {
private SearchView mSearchView;
- private Button mOpenButton;
- private Button mCloseButton;
private TextView mStatusView;
@Override
@@ -55,10 +52,6 @@
setContentView(R.layout.searchview_actionbar);
mStatusView = (TextView) findViewById(R.id.status_text);
- mOpenButton = (Button) findViewById(R.id.open_button);
- mCloseButton = (Button) findViewById(R.id.close_button);
- mOpenButton.setOnClickListener(this);
- mCloseButton.setOnClickListener(this);
}
@Override
@@ -99,7 +92,6 @@
}
mSearchView.setOnQueryTextListener(this);
- mSearchView.setOnCloseListener(this);
}
public boolean onQueryTextChange(String newText) {
@@ -117,14 +109,6 @@
return false;
}
- public void onClick(View view) {
- if (view == mCloseButton) {
- mSearchView.setIconified(true);
- } else if (view == mOpenButton) {
- mSearchView.setIconified(false);
- }
- }
-
protected boolean isAlwaysExpanded() {
return false;
}