Commit 0af1e772 authored by Trevor Johns's avatar Trevor Johns
Browse files

docs: Add new samples for N MR1

- AppShortcuts
- CommitContentSampleApp
- CommitContentSampleIME

Change-Id: I3cefc134839f944b1c0c5efc943fb779c7e7ee70
parent bf0ff8fe
......@@ -351,6 +351,9 @@ developers/build/prebuilts/gradle/DirectShare sam
developers/build/prebuilts/gradle/MidiScope samples/${PLATFORM_NAME}/media/MidiScope
developers/build/prebuilts/gradle/MidiSynth samples/${PLATFORM_NAME}/media/MidiSynth
developers/build/prebuilts/gradle/AsymmetricFingerprintDialog samples/${PLATFORM_NAME}/security/AsymmetricFingerprintDialog
developers/build/prebuilts/gradle/AppShortcuts samples/${PLATFORM_NAME}/system/AppShortcuts
developers/build/prebuilts/gradle/CommitContentSampleApp samples/${PLATFORM_NAME}/input/keyboard/CommitContentSampleApp
developers/build/prebuilts/gradle/CommitContentSampleIME samples/${PLATFORM_NAME}/input/keyboard/CommitContentSampleIME
developers/build/prebuilts/androidtv samples/${PLATFORM_NAME}/androidtv
......
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.appshortcuts">
<uses-sdk android:minSdkVersion="25" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:label="@string/app_name"
android:icon="@drawable/app"
android:resizeableActivity="true">
<activity android:name="com.example.android.appshortcuts.Main">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts"/>
</activity>
<receiver android:name="com.example.android.appshortcuts.MyReceiver">
<intent-filter>
<action android:name="android.intent.action.LOCALE_CHANGED" />
</intent-filter>
</receiver>
</application>
</manifest>
page.tags="AppShortcuts"
sample.group=System
@jd:body
<p>
This sample demonstrates how to use the Launcher Shortcuts API introduced in API 25.
This API allows an application to define a set of Intents which are displayed as
when a user long-presses on the app's launcher icon. Examples are given for
registering both links both statically in XML, as well as dynamically at runtime.
</p>
samples/browseable/AppShortcuts/res/drawable-nodpi/add.png

11.1 KB

samples/browseable/AppShortcuts/res/drawable-nodpi/app.png

15.7 KB

samples/browseable/AppShortcuts/res/drawable-nodpi/link.png

11.9 KB

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<LinearLayout
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:orientation="vertical"
android:paddingLeft="8dip"
>
<TextView
android:id="@+id/line1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#000000"
android:textSize="16sp"
/>
<TextView
android:id="@+id/line2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#444444"
/>
</LinearLayout>
<Button
android:id="@+id/remove"
android:text="@string/remove_shortcut"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:visibility="visible"
style="@android:style/Widget.Material.Button.Borderless"/>
<Button
android:id="@+id/disable"
android:text="@string/disable_shortcut"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:visibility="visible"
style="@android:style/Widget.Material.Button.Borderless"/>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="@+id/add"
android:text="@string/add_new_website"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="onAddPressed"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#444444"
android:text="@string/existing_shortcuts"
/>
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:enabled="true"
/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 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.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">アプリのショートカットサンプル</string>
<string name="add_new_website">ウェブサイト追加</string>
<string name="add_new_website_short">追加</string>
<string name="existing_shortcuts">既存のショートカット:</string>
<string name="remove_shortcut">削除</string>
<string name="disable_shortcut">無効</string>
<string name="enable_shortcut">有効</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 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.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">App Shortcuts Sample</string>
<string name="add_new_website">Add New Website</string>
<string name="add_new_website_short">Add Website</string>
<string name="existing_shortcuts">Existing shortcuts:</string>
<string name="remove_shortcut">Remove</string>
<string name="disable_shortcut">Disable</string>
<string name="enable_shortcut">Enable</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 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.
-->
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
<shortcut
android:shortcutId="add_website"
android:icon="@drawable/add"
android:shortcutShortLabel="@string/add_new_website_short"
android:shortcutLongLabel="@string/add_new_website"
>
<intent
android:action="com.example.android.appshortcuts.ADD_WEBSITE"
android:targetPackage="com.example.android.appshortcuts"
android:targetClass="com.example.android.appshortcuts.Main"
/>
</shortcut>
</shortcuts>
/*
* Copyright (C) 2016 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.appshortcuts;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.Context;
import android.content.pm.ShortcutInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class Main extends ListActivity implements OnClickListener {
static final String TAG = "ShortcutSample";
private static final String ID_ADD_WEBSITE = "add_website";
private static final String ACTION_ADD_WEBSITE =
"com.example.android.shortcutsample.ADD_WEBSITE";
private MyAdapter mAdapter;
private ShortcutHelper mHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mHelper = new ShortcutHelper(this);
mHelper.maybeRestoreAllDynamicShortcuts();
mHelper.refreshShortcuts(/*force=*/ false);
if (ACTION_ADD_WEBSITE.equals(getIntent().getAction())) {
// Invoked via the manifest shortcut.
addWebSite();
}
mAdapter = new MyAdapter(this.getApplicationContext());
setListAdapter(mAdapter);
}
@Override
protected void onResume() {
super.onResume();
refreshList();
}
/**
* Handle the add button.
*/
public void onAddPressed(View v) {
addWebSite();
}
private void addWebSite() {
Log.i(TAG, "addWebSite");
// This is important. This allows the launcher to build a prediction model.
mHelper.reportShortcutUsed(ID_ADD_WEBSITE);
final EditText editUri = new EditText(this);
editUri.setHint("http://www.android.com/");
editUri.setInputType(EditorInfo.TYPE_TEXT_VARIATION_URI);
new AlertDialog.Builder(this)
.setTitle("Add new website")
.setMessage("Type URL of a website")
.setView(editUri)
.setPositiveButton("Add", (dialog, whichButton) -> {
final String url = editUri.getText().toString().trim();
if (url.length() > 0) {
addUriAsync(url);
}
})
.show();
}
private void addUriAsync(String uri) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
mHelper.addWebSiteShortcut(uri);
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
refreshList();
}
}.execute();
}
private void refreshList() {
mAdapter.setShortcuts(mHelper.getShortcuts());
}
@Override
public void onClick(View v) {
final ShortcutInfo shortcut = (ShortcutInfo) ((View) v.getParent()).getTag();
switch (v.getId()) {
case R.id.disable:
if (shortcut.isEnabled()) {
mHelper.disableShortcut(shortcut);
} else {
mHelper.enableShortcut(shortcut);
}
refreshList();
break;
case R.id.remove:
mHelper.removeShortcut(shortcut);
refreshList();
break;
}
}
private static final List<ShortcutInfo> EMPTY_LIST = new ArrayList<>();
private String getType(ShortcutInfo shortcut) {
final StringBuilder sb = new StringBuilder();
String sep = "";
if (shortcut.isDynamic()) {
sb.append(sep);
sb.append("Dynamic");
sep = ", ";
}
if (shortcut.isPinned()) {
sb.append(sep);
sb.append("Pinned");
sep = ", ";
}
if (!shortcut.isEnabled()) {
sb.append(sep);
sb.append("Disabled");
sep = ", ";
}
return sb.toString();
}
private class MyAdapter extends BaseAdapter {
private final Context mContext;
private final LayoutInflater mInflater;
private List<ShortcutInfo> mList = EMPTY_LIST;
public MyAdapter(Context context) {
mContext = context;
mInflater = mContext.getSystemService(LayoutInflater.class);
}
@Override
public int getCount() {
return mList.size();
}
@Override
public Object getItem(int position) {
return mList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public boolean areAllItemsEnabled() {
return true;
}
@Override
public boolean isEnabled(int position) {
return true;
}
public void setShortcuts(List<ShortcutInfo> list) {
mList = list;
notifyDataSetChanged();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final View view;
if (convertView != null) {
view = convertView;
} else {
view = mInflater.inflate(R.layout.list_item, null);
}
bindView(view, position, mList.get(position));
return view;
}
public void bindView(View view, int position, ShortcutInfo shortcut) {
view.setTag(shortcut);
final TextView line1 = (TextView) view.findViewById(R.id.line1);
final TextView line2 = (TextView) view.findViewById(R.id.line2);
line1.setText(shortcut.getLongLabel());
line2.setText(getType(shortcut));
final Button remove = (Button) view.findViewById(R.id.remove);
final Button disable = (Button) view.findViewById(R.id.disable);
disable.setText(
shortcut.isEnabled() ? R.string.disable_shortcut : R.string.enable_shortcut);
remove.setOnClickListener(Main.this);
disable.setOnClickListener(Main.this);
}
}
}
/*
* Copyright (C) 2016 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.appshortcuts;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class MyReceiver extends BroadcastReceiver {
private static final String TAG = Main.TAG;
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "onReceive: " + intent);
if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {
// Refresh all shortcut to update the labels.
// (Right now shortcut labels don't contain localized strings though.)
new ShortcutHelper(context).refreshShortcuts(/*force=*/ true);
}
}
}
/*
* Copyright (C) 2016 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.appshortcuts;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.PersistableBundle;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.function.BooleanSupplier;
public class ShortcutHelper {
private static final String TAG = Main.TAG;
private static final String EXTRA_LAST_REFRESH =
"com.example.android.shortcutsample.EXTRA_LAST_REFRESH";
private static final long REFRESH_INTERVAL_MS = 60 * 60 * 1000;
private final Context mContext;
private final ShortcutManager mShortcutManager;
public ShortcutHelper(Context context) {
mContext = context;
mShortcutManager = mContext.getSystemService(ShortcutManager.class);
}
public void maybeRestoreAllDynamicShortcuts() {
if (mShortcutManager.getDynamicShortcuts().size() == 0) {
// NOTE: If this application is always supposed to have dynamic shortcuts, then publish
// them here.
// Note when an application is "restored" on a new device, all dynamic shortcuts
// will *not* be restored but the pinned shortcuts *will*.
}
}
public void reportShortcutUsed(String id) {
mShortcutManager.reportShortcutUsed(id);
}
/**
* Use this when interacting with ShortcutManager to show consistent error messages.
*/
private void callShortcutManager(BooleanSupplier r) {
try {
if (!r.getAsBoolean()) {
Utils.showToast(mContext, "Call to ShortcutManager is rate-limited");
}
} catch (Exception e) {
Log.e(TAG, "Caught Exception", e);
Utils.showToast(mContext, "Error while calling ShortcutManager: " + e.toString());
}
}
/**
* Return all mutable shortcuts from this app self.
*/
public List<ShortcutInfo> getShortcuts() {
// Load mutable dynamic shortcuts and pinned shortcuts and put them into a single list
// removing duplicates.
final List<ShortcutInfo> ret = new ArrayList<>();
final HashSet<String> seenKeys = new HashSet<>();
// Check existing shortcuts shortcuts
for (ShortcutInfo shortcut : mShortcutManager.getDynamicShortcuts()) {
if (!shortcut.isImmutable()) {
ret.add(shortcut);
seenKeys.add(shortcut.getId());
}
}
for (ShortcutInfo shortcut : mShortcutManager.getPinnedShortcuts()) {
if (!shortcut.isImmutable() && !seenKeys.contains(shortcut.getId())) {
ret.add(shortcut);
seenKeys.add(shortcut.getId());
}
}
return ret;
}
/**
* Called when the activity starts. Looks for shortcuts that have been pushed and refreshes
* them (but the refresh part isn't implemented yet...).
*/
public void refreshShortcuts(boolean force) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
Log.i(TAG, "refreshingShortcuts...");
final long now = System.currentTimeMillis();
final long staleThreshold = force ? now : now - REFRESH_INTERVAL_MS;
// Check all existing dynamic and pinned shortcut, and if their last refresh
// time is older than a certain threshold, update them.
final List<ShortcutInfo> updateList = new ArrayList<>();
for (ShortcutInfo shortcut : getShortcuts()) {
if (shortcut.isImmutable()) {
continue;
}
final PersistableBundle extras = shortcut.getExtras();
if (extras != null && extras.getLong(EXTRA_LAST_REFRESH) >= staleThreshold) {
// Shortcut still fresh.
continue;
}
Log.i(TAG, "Refreshing shortcut: " + shortcut.getId());
final ShortcutInfo.Builder b = new ShortcutInfo.Builder(
mContext, shortcut.getId());
setSiteInformation(b, shortcut.getIntent().getData());
setExtras(b);
updateList.add(b.build());
}
// Call update.
if (updateList.size() > 0) {
callShortcutManager(() -> mShortcutManager.updateShortcuts(updateList));
}
return null;
}
}.execute();
}
private ShortcutInfo createShortcutForUrl(String urlAsString) {
Log.i(TAG, "createShortcutForUrl: " + urlAsString);
final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mContext, urlAsString);
final Uri uri = Uri.parse(urlAsString);
b.setIntent(new Intent(Intent.ACTION_VIEW, uri));
setSiteInformation(b, uri);
setExtras(b);
return b.build();
}
private ShortcutInfo.Builder setSiteInformation(ShortcutInfo.Builder b, Uri uri) {
// TODO Get the actual site <title> and use it.
// TODO Set the current locale to accept-language to get localized title.
b.setShortLabel(uri.getHost());
b.setLongLabel(uri.toString());
Bitmap bmp = fetchFavicon(uri);
if (bmp != null) {
b.setIcon(Icon.createWithBitmap(bmp));
} else {
b.setIcon(Icon.createWithResource(mContext, R.drawable.link));
}
return b;
}
private ShortcutInfo.Builder setExtras(ShortcutInfo.Builder b) {
final PersistableBundle extras = new PersistableBundle();
extras.putLong(EXTRA_LAST_REFRESH, System.currentTimeMillis());
b.setExtras(extras);
return b;
}
private String normalizeUrl(String urlAsString) {
if (urlAsString.startsWith("http://") || urlAsString.startsWith("https://")) {
return urlAsString;
} else {
return "http://" + urlAsString;
}
}
public void addWebSiteShortcut(String urlAsString) {
final String uriFinal = urlAsString;
callShortcutManager(() -> {
final ShortcutInfo shortcut = createShortcutForUrl(normalizeUrl(uriFinal));
return mShortcutManager.addDynamicShortcuts(Arrays.asList(shortcut));
});
}
public void removeShortcut(ShortcutInfo shortcut) {
mShortcutManager.removeDynamicShortcuts(Arrays.asList(shortcut.getId()));
}
public void disableShortcut(ShortcutInfo shortcut) {
mShortcutManager.disableShortcuts(Arrays.asList(shortcut.getId()));
}
public void enableShortcut(ShortcutInfo shortcut) {
mShortcutManager.enableShortcuts(Arrays.asList(shortcut.getId()));
}
private Bitmap fetchFavicon(Uri uri) {
final Uri iconUri = uri.buildUpon().path("favicon.ico").build();
Log.i(TAG, "Fetching favicon from: " + iconUri);
InputStream is = null;
BufferedInputStream bis = null;
try
{
URLConnection conn = new URL(iconUri.toString()).openConnection();
conn.connect();
is = conn.getInputStream();
bis = new BufferedInputStream(is, 8192);
return BitmapFactory.decodeStream(bis);
} catch (IOException e) {
Log.w(TAG, "Failed to fetch favicon from " + iconUri, e);
return null;
}
}
}
/*
* Copyright (C) 2016 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.appshortcuts;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.widget.Toast;
public class Utils {
private Utils() {
}
public static void showToast(Context context, String message) {
new Handler(Looper.getMainLooper()).post(() -> {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
});
}
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.commitcontent.app">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
page.tags="CommitContentSampleApp"
sample.group=Input
@jd:body
<p>
This sample demonstrates how to write an application which accepts rich content
(such as images) sent from a keyboard using the Commit Content API.
</p>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 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.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black">
<WebView
android:id="@+id/commit_content_webview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#77000000"
android:orientation="vertical">
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fadeScrollbars="false"
android:scrollbars="horizontal">
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TableRow>
<TextView
android:layout_column="1"
android:gravity="end"
android:padding="3dip"
android:text="MIME"
android:textColor="@android:color/white"
android:textStyle="bold" />
<TextView
android:id="@+id/text_commit_content_mime_types"
android:padding="3dip"
android:textColor="@android:color/white" />
</TableRow>
<TableRow>
<TextView
android:layout_column="1"
android:gravity="end"
android:padding="3dip"
android:text="Label"
android:textColor="@android:color/white"
android:textStyle="bold" />
<TextView
android:id="@+id/text_commit_content_label"
android:padding="3dip"
android:textColor="@android:color/white" />
</TableRow>
<TableRow>
<TextView
android:layout_column="1"
android:gravity="end"
android:padding="3dip"
android:text="URI"
android:textColor="@android:color/white"
android:textStyle="bold" />
<TextView
android:id="@+id/text_commit_content_content_uri"
android:padding="3dip"
android:textColor="@android:color/white" />
</TableRow>
<TableRow>
<TextView
android:layout_column="1"
android:gravity="end"
android:padding="3dip"
android:text="Link"
android:textColor="@android:color/white"
android:textStyle="bold" />
<TextView
android:id="@+id/text_commit_content_link_uri"
android:padding="3dip"
android:textColor="@android:color/white" />
</TableRow>
<TableRow>
<TextView
android:layout_column="1"
android:gravity="end"
android:padding="3dip"
android:text="Flags"
android:textColor="@android:color/white"
android:textStyle="bold" />
<TextView
android:id="@+id/text_commit_content_link_flags"
android:padding="3dip"
android:textColor="@android:color/white" />
</TableRow>
</TableLayout>
</HorizontalScrollView>
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:fadeScrollbars="false"
android:scrollbars="vertical">
<LinearLayout
android:id="@+id/commit_content_sample_edit_boxes"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</ScrollView>
</LinearLayout>
</FrameLayout>
samples/browseable/CommitContentSampleApp/res/mipmap-hdpi/ic_launcher.png

3.34 KB

samples/browseable/CommitContentSampleApp/res/mipmap-mdpi/ic_launcher.png

2.15 KB

Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment