diff options
author | Manuel Vivo <mvivo@google.com> | 2019-02-19 15:29:33 +0100 |
---|---|---|
committer | Chris Banes <chrisbanes@google.com> | 2019-03-06 23:33:23 +0000 |
commit | 0f84a4779d867eab4512dd39448edd571ba77c0c (patch) | |
tree | c35ebaa9139f648a5410ba8cbbd9b41ed64e7ed2 /content/SharingShortcuts | |
parent | 0924d82a7de91b08d84cd907d024924a93177a3c (diff) | |
download | android-0f84a4779d867eab4512dd39448edd571ba77c0c.tar.gz |
Create code sample for the new DirectShare API: Sharing Shortcuts
Test: Tested in an Android Q device
Change-Id: I388b8108df482837dabc7c042e4fb0a0004af625
Diffstat (limited to 'content/SharingShortcuts')
43 files changed, 1467 insertions, 0 deletions
diff --git a/content/SharingShortcuts/Application/.gitignore b/content/SharingShortcuts/Application/.gitignore new file mode 100644 index 00000000..6eb878d4 --- /dev/null +++ b/content/SharingShortcuts/Application/.gitignore @@ -0,0 +1,16 @@ +# Copyright 2013 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. +src/template/ +src/common/ +build.gradle diff --git a/content/SharingShortcuts/Application/proguard-project.txt b/content/SharingShortcuts/Application/proguard-project.txt new file mode 100644 index 00000000..f2fe1559 --- /dev/null +++ b/content/SharingShortcuts/Application/proguard-project.txt @@ -0,0 +1,20 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/content/SharingShortcuts/Application/src/androidTest/java/com/example/android/sharingshortcuts/test/SampleTest.java b/content/SharingShortcuts/Application/src/androidTest/java/com/example/android/sharingshortcuts/test/SampleTest.java new file mode 100644 index 00000000..0a5bd704 --- /dev/null +++ b/content/SharingShortcuts/Application/src/androidTest/java/com/example/android/sharingshortcuts/test/SampleTest.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2019 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.sharingshortcuts; + +import android.test.ActivityInstrumentationTestCase2; + +/** + * Tests for DirectShare sample. + */ +public class SampleTest extends ActivityInstrumentationTestCase2<MainActivity> { + + private MainActivity mTestActivity; + + public SampleTest() { + super(MainActivity.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + mTestActivity = getActivity(); + } + + /** + * Test if the test fixture has been set up correctly. + */ + public void testPreconditions() { + assertNotNull("mTestActivity is null", mTestActivity); + } + +} diff --git a/content/SharingShortcuts/Application/src/main/AndroidManifest.xml b/content/SharingShortcuts/Application/src/main/AndroidManifest.xml new file mode 100644 index 00000000..626381c1 --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/AndroidManifest.xml @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8"?><!-- + Copyright 2019 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" + xmlns:tools="http://schemas.android.com/tools" + package="com.example.android.sharingshortcuts" + android:versionCode="1" + android:versionName="1.0"> + + <application + android:allowBackup="true" + android:icon="@mipmap/ic_launcher" + android:label="@string/app_name" + android:theme="@style/SharingShortcutsTheme" + tools:ignore="GoogleAppIndexingWarning"> + + <activity + android:name=".MainActivity" + android:label="@string/app_name"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + <!-- Reference resource file where the app's shortcuts are defined --> + <meta-data + android:name="android.app.shortcuts" + android:resource="@xml/shortcuts" /> + </activity> + + <activity + android:name=".SendMessageActivity" + android:label="@string/app_name" + android:theme="@style/SharingShortcutsDialogTheme"> + <!-- This activity can respond to Intents of type SEND and with text/plain data --> + <intent-filter> + <action android:name="android.intent.action.SEND" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:mimeType="text/plain" /> + </intent-filter> + <!-- Only needed if you import the sharetarget AndroidX library that provides + backwards compatibility with the old DirectShare API. + The activity that receives the Sharing Shortcut intent needs to be taken into + account with this chooser target provider. --> + <meta-data + android:name="android.service.chooser.chooser_target_service" + android:value="androidx.sharetarget.ChooserTargetServiceCompat" /> + </activity> + + <activity + android:name=".SelectContactActivity" + android:label="@string/app_name" + android:theme="@style/SharingShortcutsDialogTheme" /> + + </application> + +</manifest> diff --git a/content/SharingShortcuts/Application/src/main/java/com/example/android/sharingshortcuts/Contact.java b/content/SharingShortcuts/Application/src/main/java/com/example/android/sharingshortcuts/Contact.java new file mode 100644 index 00000000..155a8412 --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/java/com/example/android/sharingshortcuts/Contact.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2019 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.sharingshortcuts; + +import androidx.annotation.NonNull; + +/** + * Provides the list of dummy contacts. This sample implements this as constants, but real-life apps + * should use a database and such. + */ +public class Contact { + + /** + * The list of dummy contacts. + */ + public static final Contact[] CONTACTS = { + new Contact("Tereasa"), + new Contact("Chang"), + new Contact("Kory"), + new Contact("Clare"), + new Contact("Landon"), + new Contact("Kyle"), + new Contact("Deana"), + new Contact("Daria"), + new Contact("Melisa"), + new Contact("Sammie"), + }; + + /** + * The contact ID. + */ + public static final String ID = "contact_id"; + + /** + * Representative invalid contact ID. + */ + public static final int INVALID_ID = -1; + + /** + * The name of this contact. + */ + private final String mName; + + /** + * Instantiates a new {@link Contact}. + * + * @param name The name of the contact. + */ + public Contact(@NonNull String name) { + mName = name; + } + + /** + * Finds a {@link Contact} specified by a contact ID. + * + * @param id The contact ID. This needs to be a valid ID. + * @return A {@link Contact} + */ + public static Contact byId(int id) { + return CONTACTS[id]; + } + + /** + * Gets the name of this contact. + * + * @return The name of this contact. + */ + public String getName() { + return mName; + } + + /** + * Gets the icon of this contact. + * + * @return The icon. + */ + public int getIcon() { + return R.mipmap.logo_avatar; + } + +} diff --git a/content/SharingShortcuts/Application/src/main/java/com/example/android/sharingshortcuts/ContactViewBinder.java b/content/SharingShortcuts/Application/src/main/java/com/example/android/sharingshortcuts/ContactViewBinder.java new file mode 100644 index 00000000..86925922 --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/java/com/example/android/sharingshortcuts/ContactViewBinder.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2019 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.sharingshortcuts; + +import android.widget.TextView; + +/** + * A simple utility to bind a {@link TextView} with a {@link Contact}. + */ +public class ContactViewBinder { + + /** + * Binds the {@code textView} with the specified {@code contact}. + * + * @param contact The contact. + * @param textView The TextView. + */ + public static void bind(Contact contact, TextView textView) { + textView.setText(contact.getName()); + textView.setCompoundDrawablesRelativeWithIntrinsicBounds(contact.getIcon(), 0, 0, 0); + } + +} diff --git a/content/SharingShortcuts/Application/src/main/java/com/example/android/sharingshortcuts/MainActivity.java b/content/SharingShortcuts/Application/src/main/java/com/example/android/sharingshortcuts/MainActivity.java new file mode 100644 index 00000000..a0709bd4 --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/java/com/example/android/sharingshortcuts/MainActivity.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2019 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.sharingshortcuts; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.EditText; + +/** + * Provides the landing screen of this sample. There is nothing particularly interesting here. All + * the codes related to the Direct Share feature are in {@link SharingShortcutsManager}. + */ +public class MainActivity extends Activity { + + private EditText mEditBody; + private SharingShortcutsManager mSharingShortcutsManager; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + mEditBody = findViewById(R.id.body); + findViewById(R.id.share).setOnClickListener(mOnClickListener); + + mSharingShortcutsManager = new SharingShortcutsManager(); + mSharingShortcutsManager.pushDirectShareTargets(this); + } + + private View.OnClickListener mOnClickListener = new View.OnClickListener() { + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.share: + share(); + break; + } + } + }; + + /** + * Emits a sample share {@link Intent}. + */ + private void share() { + Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND); + sharingIntent.setType("text/plain"); + sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, mEditBody.getText().toString()); + startActivity(Intent.createChooser(sharingIntent, getString(R.string.send_intent_title))); + } +} diff --git a/content/SharingShortcuts/Application/src/main/java/com/example/android/sharingshortcuts/SelectContactActivity.java b/content/SharingShortcuts/Application/src/main/java/com/example/android/sharingshortcuts/SelectContactActivity.java new file mode 100644 index 00000000..4e4d5437 --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/java/com/example/android/sharingshortcuts/SelectContactActivity.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2019 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.sharingshortcuts; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +/** + * The dialog for selecting a contact to share the text with. This dialog is shown when the user + * taps on this sample's icon rather than any of the Direct Share contacts. + */ +public class SelectContactActivity extends Activity { + + /** + * The action string for Intents. + */ + public static final String ACTION_SELECT_CONTACT = + "com.example.android.sharingshortcuts.intent.action.SELECT_CONTACT"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_select_contact); + Intent intent = getIntent(); + if (!ACTION_SELECT_CONTACT.equals(intent.getAction())) { + finish(); + return; + } + // Set up the list of contacts + RecyclerView recyclerView = findViewById(R.id.recycler_view); + recyclerView.setAdapter(mContactAdapter); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + } + + private final RecyclerView.Adapter mContactAdapter = + new RecyclerView.Adapter<ContactViewHolder>() { + + @NonNull + @Override + public ContactViewHolder onCreateViewHolder(@NonNull ViewGroup parent, + int viewType) { + TextView textView = (TextView) LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_contact, parent, false); + return new ContactViewHolder(textView); + } + + @Override + public void onBindViewHolder(@NonNull ContactViewHolder holder, + final int position) { + Contact contact = Contact.CONTACTS[position]; + ContactViewBinder.bind(contact, (TextView) holder.itemView); + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent data = new Intent(); + data.putExtra(Contact.ID, position); + setResult(RESULT_OK, data); + finish(); + } + }); + } + + @Override + public int getItemCount() { + return Contact.CONTACTS.length; + } + }; + + private static class ContactViewHolder extends RecyclerView.ViewHolder { + + ContactViewHolder(@NonNull TextView textView) { + super(textView); + } + } +} diff --git a/content/SharingShortcuts/Application/src/main/java/com/example/android/sharingshortcuts/SendMessageActivity.java b/content/SharingShortcuts/Application/src/main/java/com/example/android/sharingshortcuts/SendMessageActivity.java new file mode 100644 index 00000000..7519a7b8 --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/java/com/example/android/sharingshortcuts/SendMessageActivity.java @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2019 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.sharingshortcuts; + +import android.app.Activity; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +/** + * Provides the UI for sharing a text with a {@link Contact}. + */ +public class SendMessageActivity extends Activity { + + /** + * The request code for {@link SelectContactActivity}. This is used when the user doesn't + * select any of Direct Share icons. + */ + private static final int REQUEST_SELECT_CONTACT = 1; + + /** + * The text to share. + */ + private String mBody; + + /** + * The ID of the contact to share the text with. + */ + private int mContactId; + + // View references. + private TextView mTextContactName; + private TextView mTextMessageBody; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_send_message); + setTitle(R.string.sending_message); + // View references. + mTextContactName = findViewById(R.id.contact_name); + mTextMessageBody = findViewById(R.id.message_body); + // Handle the share Intent. + boolean handled = handleIntent(getIntent()); + if (!handled) { + finish(); + return; + } + // Bind event handlers. + findViewById(R.id.send).setOnClickListener(mOnClickListener); + // Set up the UI. + prepareUi(); + // The contact ID will not be passed on when the user clicks on the app icon rather than any + // of the Direct Share icons. In this case, we show another dialog for selecting a contact. + if (mContactId == Contact.INVALID_ID) { + selectContact(); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + switch (requestCode) { + case REQUEST_SELECT_CONTACT: + if (resultCode == RESULT_OK) { + mContactId = data.getIntExtra(Contact.ID, Contact.INVALID_ID); + } + // Give up sharing the send_message if the user didn't choose a contact. + if (mContactId == Contact.INVALID_ID) { + finish(); + return; + } + prepareUi(); + break; + default: + super.onActivityResult(requestCode, resultCode, data); + } + } + + /** + * Handles the passed {@link Intent}. This method can only handle intents for sharing a plain + * text. {@link #mBody} and {@link #mContactId} are modified accordingly. + * + * @param intent The {@link Intent}. + * @return true if the {@code intent} is handled properly. + */ + private boolean handleIntent(Intent intent) { + if (Intent.ACTION_SEND.equals(intent.getAction()) + && "text/plain".equals(intent.getType())) { + mBody = intent.getStringExtra(Intent.EXTRA_TEXT); + // The intent comes from Direct share + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P + && intent.hasExtra(Intent.EXTRA_SHORTCUT_ID)) { + String shortcutId = intent.getStringExtra(Intent.EXTRA_SHORTCUT_ID); + mContactId = Integer.valueOf(shortcutId); + } else { + // The text was shared and the user chose our app + mContactId = Contact.INVALID_ID; + } + return true; + } + return false; + } + + /** + * Sets up the UI. + */ + private void prepareUi() { + if (mContactId != Contact.INVALID_ID) { + Contact contact = Contact.byId(mContactId); + ContactViewBinder.bind(contact, mTextContactName); + } + mTextMessageBody.setText(mBody); + } + + /** + * Delegates selection of a {@Contact} to {@link SelectContactActivity}. + */ + private void selectContact() { + Intent intent = new Intent(this, SelectContactActivity.class); + intent.setAction(SelectContactActivity.ACTION_SELECT_CONTACT); + startActivityForResult(intent, REQUEST_SELECT_CONTACT); + } + + private View.OnClickListener mOnClickListener = new View.OnClickListener() { + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.send: + send(); + break; + } + } + }; + + /** + * Pretends to send the text to the contact. This only shows a dummy message. + */ + private void send() { + Toast.makeText(this, + getString(R.string.message_sent, mBody, Contact.byId(mContactId).getName()), + Toast.LENGTH_SHORT).show(); + finish(); + } + +} diff --git a/content/SharingShortcuts/Application/src/main/java/com/example/android/sharingshortcuts/SharingShortcutsManager.java b/content/SharingShortcuts/Application/src/main/java/com/example/android/sharingshortcuts/SharingShortcutsManager.java new file mode 100644 index 00000000..14cc9290 --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/java/com/example/android/sharingshortcuts/SharingShortcutsManager.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2019 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.sharingshortcuts; + +import android.content.Context; +import android.content.Intent; + +import androidx.annotation.NonNull; +import androidx.core.app.Person; +import androidx.core.content.pm.ShortcutInfoCompat; +import androidx.core.content.pm.ShortcutManagerCompat; +import androidx.core.graphics.drawable.IconCompat; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + +/** + * Provides the Sharing Shortcuts items to the system. + * <p> + * Use the ShortcutManagerCompat to make it work on older Android versions + * without any extra work needed. + * <p> + * Interactions with the ShortcutManager API can happen on any thread. + */ +public class SharingShortcutsManager { + + /** + * Define maximum number of shortcuts. + * Don't add more than {@link ShortcutManagerCompat#getMaxShortcutCountPerActivity(Context)}. + */ + private static final int MAX_SHORTCUTS = 4; + + /** + * Category name defined in res/xml/shortcuts.xml that accepts data of type text/plain + * and will trigger {@link SendMessageActivity} + */ + private static final String CATEGORY_TEXT_SHARE_TARGET = + "com.example.android.sharingshortcuts.category.TEXT_SHARE_TARGET"; + + /** + * Publish the list of dynamics shortcuts that will be used in Direct Share. + * <p> + * For each shortcut, we specify the categories that it will be associated to, + * the intent that will trigger when opened as a static launcher shortcut, + * and the Shortcut ID between other things. + * <p> + * The Shortcut ID that we specify in the {@link ShortcutInfoCompat.Builder} constructor will + * be received in the intent as {@link Intent#EXTRA_SHORTCUT_ID}. + * <p> + * In this code sample, this method is completely static. We are always setting the same sharing + * shortcuts. In a real-world example, we would replace existing shortcuts depending on + * how the user interacts with the app as often as we want to. + */ + public void pushDirectShareTargets(@NonNull Context context) { + ArrayList<ShortcutInfoCompat> shortcuts = new ArrayList<>(); + + // Category that our sharing shortcuts will be assigned to + Set<String> contactCategories = new HashSet<>(); + contactCategories.add(CATEGORY_TEXT_SHARE_TARGET); + + // Adding maximum number of shortcuts to the list + for (int id = 0; id < MAX_SHORTCUTS; ++id) { + Contact contact = Contact.byId(id); + + // Item that will be sent if the shortcut is opened as a static launcher shortcut + Intent staticLauncherShortcutIntent = new Intent(Intent.ACTION_DEFAULT); + + // Creates a new Sharing Shortcut and adds it to the list + // The id passed in the constructor will become EXTRA_SHORTCUT_ID in the received Intent + shortcuts.add(new ShortcutInfoCompat.Builder(context, Integer.toString(id)) + .setShortLabel(contact.getName()) + // Icon that will be displayed in the share target + .setIcon(IconCompat.createWithResource(context, contact.getIcon())) + .setIntent(staticLauncherShortcutIntent) + // Make this sharing shortcut cached by the system + // Even if it is unpublished, it can still appear on the sharesheet + .setLongLived() + .setCategories(contactCategories) + // Person objects are used to give better suggestions + .setPerson(new Person.Builder() + .setName(contact.getName()) + .build()) + .build()); + } + + ShortcutManagerCompat.addDynamicShortcuts(context, shortcuts); + } + + /** + * Remove all dynamic shortcuts + */ + public void removeAllDirectShareTargets(@NonNull Context context) { + ShortcutManagerCompat.removeAllDynamicShortcuts(context); + } +} diff --git a/content/SharingShortcuts/Application/src/main/res/layout/activity_main.xml b/content/SharingShortcuts/Application/src/main/res/layout/activity_main.xml new file mode 100644 index 00000000..524303d8 --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/res/layout/activity_main.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + Copyright (C) 2019 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="match_parent" + android:orientation="vertical"> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_margin="@dimen/margin_medium" + android:text="@string/explanation" /> + + <View + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="@android:color/darker_gray" /> + + <EditText + android:id="@+id/body" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/margin_medium" + android:layout_marginTop="@dimen/margin_medium" + android:layout_marginEnd="@dimen/margin_medium" + android:hint="@string/text_to_share" + android:text="@string/hello" /> + + <Button + android:id="@+id/share" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="end" + android:layout_marginStart="@dimen/margin_medium" + android:layout_marginEnd="@dimen/margin_medium" + android:text="@string/share" /> + +</LinearLayout>
\ No newline at end of file diff --git a/content/SharingShortcuts/Application/src/main/res/layout/activity_select_contact.xml b/content/SharingShortcuts/Application/src/main/res/layout/activity_select_contact.xml new file mode 100644 index 00000000..b9cd8032 --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/res/layout/activity_select_contact.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + Copyright (C) 2019 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. + --> +<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/recycler_view" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_marginTop="@dimen/margin_medium" + android:clipToPadding="false" + android:divider="@null" + android:paddingTop="@dimen/margin_tiny" + android:paddingBottom="@dimen/margin_tiny" /> diff --git a/content/SharingShortcuts/Application/src/main/res/layout/activity_send_message.xml b/content/SharingShortcuts/Application/src/main/res/layout/activity_send_message.xml new file mode 100644 index 00000000..b8ad5957 --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/res/layout/activity_send_message.xml @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + Copyright (C) 2019 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" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/dialog_padding" + android:layout_marginTop="@dimen/dialog_padding" + android:layout_marginEnd="@dimen/dialog_padding" + android:orientation="horizontal"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:gravity="center_vertical" + android:text="@string/to" + android:textAppearance="@android:style/TextAppearance.Material.Caption" /> + + <TextView + android:id="@+id/contact_name" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/margin_medium" + android:layout_weight="1" + android:drawablePadding="@dimen/margin_medium" + android:gravity="center_vertical" + android:textAppearance="@android:style/TextAppearance.Material.Body1" + tools:drawableStart="@mipmap/logo_avatar" + tools:text="Taro" /> + + </LinearLayout> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/dialog_padding" + android:layout_marginTop="@dimen/margin_medium" + android:layout_marginEnd="@dimen/dialog_padding" + android:gravity="center_vertical" + android:text="@string/body" + android:textAppearance="@android:style/TextAppearance.Material.Caption" /> + + <TextView + android:id="@+id/message_body" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/dialog_padding" + android:layout_marginEnd="@dimen/dialog_padding" + android:gravity="top" + android:hint="@string/hint_body" + android:paddingTop="@dimen/margin_small" + android:paddingBottom="@dimen/margin_small" + android:textAppearance="@android:style/TextAppearance.Material.Body1" + tools:text="Hello, world!" /> + + <Button + android:id="@+id/send" + style="@android:style/Widget.Material.Button.Borderless.Colored" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="end" + android:layout_marginEnd="@dimen/dialog_button_padding" + android:layout_marginBottom="@dimen/dialog_button_padding" + android:text="@string/send" /> + +</LinearLayout> diff --git a/content/SharingShortcuts/Application/src/main/res/layout/item_contact.xml b/content/SharingShortcuts/Application/src/main/res/layout/item_contact.xml new file mode 100644 index 00000000..a7c17354 --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/res/layout/item_contact.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + Copyright (C) 2019 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. + --> +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/contact_name" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:drawablePadding="@dimen/margin_medium" + android:gravity="center_vertical" + android:paddingStart="?android:attr/listPreferredItemPaddingStart" + android:paddingTop="@dimen/margin_tiny" + android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" + android:paddingBottom="@dimen/margin_tiny" + tools:drawableStart="@mipmap/logo_avatar" + tools:text="Taro" /> diff --git a/content/SharingShortcuts/Application/src/main/res/mipmap-hdpi/ic_launcher.png b/content/SharingShortcuts/Application/src/main/res/mipmap-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..988f2ec8 --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/content/SharingShortcuts/Application/src/main/res/mipmap-hdpi/logo_avatar.png b/content/SharingShortcuts/Application/src/main/res/mipmap-hdpi/logo_avatar.png Binary files differnew file mode 100644 index 00000000..8892c08d --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/res/mipmap-hdpi/logo_avatar.png diff --git a/content/SharingShortcuts/Application/src/main/res/mipmap-mdpi/ic_launcher.png b/content/SharingShortcuts/Application/src/main/res/mipmap-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..0baa1cc7 --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/content/SharingShortcuts/Application/src/main/res/mipmap-mdpi/logo_avatar.png b/content/SharingShortcuts/Application/src/main/res/mipmap-mdpi/logo_avatar.png Binary files differnew file mode 100644 index 00000000..c2de7747 --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/res/mipmap-mdpi/logo_avatar.png diff --git a/content/SharingShortcuts/Application/src/main/res/mipmap-xhdpi/ic_launcher.png b/content/SharingShortcuts/Application/src/main/res/mipmap-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..da0aa2f2 --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/content/SharingShortcuts/Application/src/main/res/mipmap-xhdpi/logo_avatar.png b/content/SharingShortcuts/Application/src/main/res/mipmap-xhdpi/logo_avatar.png Binary files differnew file mode 100644 index 00000000..10c2dc9a --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/res/mipmap-xhdpi/logo_avatar.png diff --git a/content/SharingShortcuts/Application/src/main/res/mipmap-xxhdpi/ic_launcher.png b/content/SharingShortcuts/Application/src/main/res/mipmap-xxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..e1cc1ff1 --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/content/SharingShortcuts/Application/src/main/res/mipmap-xxhdpi/logo_avatar.png b/content/SharingShortcuts/Application/src/main/res/mipmap-xxhdpi/logo_avatar.png Binary files differnew file mode 100644 index 00000000..df02f04f --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/res/mipmap-xxhdpi/logo_avatar.png diff --git a/content/SharingShortcuts/Application/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/content/SharingShortcuts/Application/src/main/res/mipmap-xxxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..8b0f60c4 --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/res/mipmap-xxxhdpi/ic_launcher.png diff --git a/content/SharingShortcuts/Application/src/main/res/mipmap-xxxhdpi/logo_avatar.png b/content/SharingShortcuts/Application/src/main/res/mipmap-xxxhdpi/logo_avatar.png Binary files differnew file mode 100644 index 00000000..dc8d3769 --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/res/mipmap-xxxhdpi/logo_avatar.png diff --git a/content/SharingShortcuts/Application/src/main/res/values/colors.xml b/content/SharingShortcuts/Application/src/main/res/values/colors.xml new file mode 100644 index 00000000..4ffc20b8 --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/res/values/colors.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + Copyright (C) 2019 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> + <color name="primary">#3F51B5</color> + <color name="primary_dark">#303F9F</color> + <color name="primary_light">#C5CAE9</color> + <color name="accent">#00BCD4</color> + <color name="primary_text">#212121</color> + <color name="secondary_text">#727272</color> + <color name="icons">#FFFFFF</color> + <color name="divider">#B6B6B6</color> +</resources> diff --git a/content/SharingShortcuts/Application/src/main/res/values/dimens.xml b/content/SharingShortcuts/Application/src/main/res/values/dimens.xml new file mode 100644 index 00000000..dce82532 --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/res/values/dimens.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + Copyright (C) 2019 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> + <dimen name="dialog_padding">24dp</dimen> + <dimen name="dialog_button_padding">8dp</dimen> +</resources>
\ No newline at end of file diff --git a/content/SharingShortcuts/Application/src/main/res/values/strings.xml b/content/SharingShortcuts/Application/src/main/res/values/strings.xml new file mode 100644 index 00000000..6b395510 --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/res/values/strings.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + Copyright (C) 2019 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> + + <!-- MainActivity --> + + <string name="send_intent_title">Send a message via:</string> + <string name="explanation"> + This app demonstrates how to implement Direct Share. Use some other app and share a text. + For your convenience, you can also use the input below to share the text. + </string> + <string name="text_to_share">Text to share</string> + <string name="hello">Hello!</string> + <string name="share">Share</string> + + <!-- SendMessageActivity --> + + <string name="sending_message">Sending a message</string> + <string name="to">To:</string> + <string name="send">Send</string> + <string name="body">Body:</string> + <string name="hint_body">Edit your message</string> + <string name="message_sent">Sent a message \"%1$s\" to %2$s</string> + +</resources>
\ No newline at end of file diff --git a/content/SharingShortcuts/Application/src/main/res/values/styles.xml b/content/SharingShortcuts/Application/src/main/res/values/styles.xml new file mode 100644 index 00000000..ca1a0e7b --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/res/values/styles.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + Copyright (C) 2019 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> + + <style name="SharingShortcutsTheme" parent="android:Theme.Material.Light.DarkActionBar"> + <item name="android:colorPrimary">@color/primary</item> + <item name="android:colorPrimaryDark">@color/primary_dark</item> + <item name="android:colorAccent">@color/accent</item> + </style> + + <style name="SharingShortcutsDialogTheme" parent="android:Theme.Material.Light.Dialog"> + <item name="android:colorPrimary">@color/primary</item> + <item name="android:colorPrimaryDark">@color/primary_dark</item> + <item name="android:colorAccent">@color/accent</item> + </style> + + +</resources>
\ No newline at end of file diff --git a/content/SharingShortcuts/Application/src/main/res/xml/shortcuts.xml b/content/SharingShortcuts/Application/src/main/res/xml/shortcuts.xml new file mode 100644 index 00000000..7e6b24dc --- /dev/null +++ b/content/SharingShortcuts/Application/src/main/res/xml/shortcuts.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + Copyright (C) 2019 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. + --> +<shorcuts xmlns:android="http://schemas.android.com/apk/res/android"> + <share-target android:targetClass="com.example.android.sharingshortcuts.SendMessageActivity"> + <data android:mimeType="text/plain" /> + <category android:name="com.example.android.sharingshortcuts.category.TEXT_SHARE_TARGET" /> + </share-target> +</shorcuts>
\ No newline at end of file diff --git a/content/SharingShortcuts/build.gradle b/content/SharingShortcuts/build.gradle new file mode 100644 index 00000000..9fa56856 --- /dev/null +++ b/content/SharingShortcuts/build.gradle @@ -0,0 +1,21 @@ + + +// BEGIN_EXCLUDE +import com.example.android.samples.build.SampleGenPlugin +apply plugin: SampleGenPlugin + +samplegen { + pathToBuild "../../../../build" + pathToSamplesCommon "../../common" +} +apply from: "../../../../build/build.gradle" +buildscript { + ext.kotlin_version = '1.3.21' + repositories { + mavenCentral() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} +// END_EXCLUDE diff --git a/content/SharingShortcuts/buildSrc/build.gradle b/content/SharingShortcuts/buildSrc/build.gradle new file mode 100644 index 00000000..75b00eeb --- /dev/null +++ b/content/SharingShortcuts/buildSrc/build.gradle @@ -0,0 +1,17 @@ + +repositories { + google() + jcenter() +} +dependencies { + implementation 'org.freemarker:freemarker:2.3.20' +} + +sourceSets { + main { + groovy { + srcDir new File(rootDir, "../../../../../build/buildSrc/src/main/groovy") + } + } +} + diff --git a/content/SharingShortcuts/gradle.properties b/content/SharingShortcuts/gradle.properties new file mode 100644 index 00000000..94f84728 --- /dev/null +++ b/content/SharingShortcuts/gradle.properties @@ -0,0 +1,22 @@ + +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Settings specified in this file will override any Gradle settings +# configured through the IDE. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx10248m -XX:MaxPermSize=256m +# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +android.useAndroidX=true +android.enableJetifier=true diff --git a/content/SharingShortcuts/gradle/wrapper/gradle-wrapper.jar b/content/SharingShortcuts/gradle/wrapper/gradle-wrapper.jar Binary files differnew file mode 100644 index 00000000..8c0fb64a --- /dev/null +++ b/content/SharingShortcuts/gradle/wrapper/gradle-wrapper.jar diff --git a/content/SharingShortcuts/gradle/wrapper/gradle-wrapper.properties b/content/SharingShortcuts/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..77cff654 --- /dev/null +++ b/content/SharingShortcuts/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Mon Feb 18 15:19:26 CET 2019 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip diff --git a/content/SharingShortcuts/gradlew b/content/SharingShortcuts/gradlew new file mode 100755 index 00000000..91a7e269 --- /dev/null +++ b/content/SharingShortcuts/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/content/SharingShortcuts/gradlew.bat b/content/SharingShortcuts/gradlew.bat new file mode 100644 index 00000000..aec99730 --- /dev/null +++ b/content/SharingShortcuts/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/content/SharingShortcuts/screenshots/1-main.png b/content/SharingShortcuts/screenshots/1-main.png Binary files differnew file mode 100644 index 00000000..693b2be3 --- /dev/null +++ b/content/SharingShortcuts/screenshots/1-main.png diff --git a/content/SharingShortcuts/screenshots/2-intent.png b/content/SharingShortcuts/screenshots/2-intent.png Binary files differnew file mode 100644 index 00000000..a6dee107 --- /dev/null +++ b/content/SharingShortcuts/screenshots/2-intent.png diff --git a/content/SharingShortcuts/screenshots/3-message.png b/content/SharingShortcuts/screenshots/3-message.png Binary files differnew file mode 100644 index 00000000..cde24969 --- /dev/null +++ b/content/SharingShortcuts/screenshots/3-message.png diff --git a/content/SharingShortcuts/screenshots/4-static_shortcuts.png b/content/SharingShortcuts/screenshots/4-static_shortcuts.png Binary files differnew file mode 100644 index 00000000..0404027b --- /dev/null +++ b/content/SharingShortcuts/screenshots/4-static_shortcuts.png diff --git a/content/SharingShortcuts/screenshots/icon-web.png b/content/SharingShortcuts/screenshots/icon-web.png Binary files differnew file mode 100644 index 00000000..ee7c5579 --- /dev/null +++ b/content/SharingShortcuts/screenshots/icon-web.png diff --git a/content/SharingShortcuts/settings.gradle b/content/SharingShortcuts/settings.gradle new file mode 100644 index 00000000..0a5c310b --- /dev/null +++ b/content/SharingShortcuts/settings.gradle @@ -0,0 +1,2 @@ + +include 'Application' diff --git a/content/SharingShortcuts/template-params.xml b/content/SharingShortcuts/template-params.xml new file mode 100644 index 00000000..414e4e45 --- /dev/null +++ b/content/SharingShortcuts/template-params.xml @@ -0,0 +1,107 @@ +<?xml version="1.0" encoding="UTF-8"?><!-- + Copyright 2013 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. +--> + +<sample> + <name>SharingShortcuts</name> + <group>Content</group> + <package>com.example.android.sharingshortcuts</package> + + <minSdk>21</minSdk> + + <!-- Include additional dependencies here.--> + <dependency>androidx.appcompat:appcompat:1.1.0-alpha03</dependency> + <dependency>androidx.sharetarget:sharetarget:1.0.0-alpha01</dependency> + <dependency>androidx.recyclerview:recyclerview:1.0.0</dependency> + + <strings> + <intro> + <![CDATA[ +This sample demonstrates how to provide the Sharing Shortcuts - Direct Share feature. The app shows +some options directly in the list of share intent candidates and launcher shortcuts. + ]]> + </intro> + </strings> + + <template src="base" /> + <androidX>true</androidX> + + <metadata> + <!-- Values: {DRAFT | PUBLISHED | INTERNAL | DEPRECATED | SUPERCEDED} --> + <status>DRAFT</status> + <categories>Content</categories> + <technologies>Android</technologies> + <languages>Java</languages> + <solutions>Mobile</solutions> + <level>INTERMEDIATE</level> + <icon>screenshots/icon-web.png</icon> + <screenshots> + <img>screenshots/1-main.png</img> + <img>screenshots/2-intent.png</img> + <img>screenshots/3-message.png</img> + <img>screenshots/4-static_shortcuts.png</img> + </screenshots> + + <api_refs> + <androidx>androidx.core.content.pm.ShortcutManagerCompat</androidx> + <androidx>androidx.core.content.pm.ShortcutInfoCompat</androidx> + </api_refs> + <description> + <![CDATA[ +Sample demonstrating how to show some options directly in the list of share intent candidates. + ]]> + </description> + + <intro> + <![CDATA[ +Direct Share is a feature that allows apps to show their internal options directly in the +system Intent chooser dialog. This sample is a dummy messaging app, and just like any other +messaging apps, it receives intents for sharing a plain text. When a user shares some text from some +other app, this sample app will be listed as an option. Using the Direct Share feature, this app +also shows some of contacts directly in the chooser dialog. + +Direct Share was [first introduced][1] in Android M where you had to implement a service to provide +direct share targets on demand. The way to do that changed in Android Q, you need to provide your +direct share targets in advance. First, you have to declare share-target elements in the same +application's resource file than [static shortcuts][2]. Then, you need to publish dynamic +shortcuts with the same category you declared in the share-target with the [ShortcutManager API][3]. +You will need to manually update the list of shortcuts every time you consider it appropriate. +The API offers methods to update, remove or add shortcuts. You can use the +[ShortcutInfoCompat.Builder][4] to customize your shortcut. If you don't want to block the UI thread +doing these operations, interactions with the ShortcutManager can also happen on a background thread. + +There are three ways the app is sending/receiving intents: +- Dynamic Share: The user selected the app in the sharesheet to receive the text. After this, +the user will have to select the contact to share the text with. In our case, the app receives an +intent of type Intent.ACTION_SEND. +- Direct Share: The user selected a person of your app in the sharesheet to share the text with. +The received intent of type Intent.ACTION_SEND will contain a String EXTRA_SHORTCUT_ID that will +have the id of the shortcut that was selected. After this, the app is ready to send the text. +- Launcher shortcut: When the user taps on a launcher shortcut, the intent that was +added to the shortcut will get fired. In our case, it triggers an intent of type Intent.ACTION_DEFAULT. + +To make Direct Share backwards compatible with older Android versions, you need to add the AndroidX +sharetarget library and in your AndroidManifest.xml, add a meta-data tag in your Activity that +receives the Intent. Specify android:name as android.service.chooser.chooser_target_service and +android:value as androidx.sharetarget.ChooserTargetServiceCompat. + +[1]: https://developer.android.com/about/versions/marshmallow/android-6.0#direct-share +[2]: https://developer.android.com/guide/topics/ui/shortcuts/creating-shortcuts +[3]: https://developer.android.com/reference/androidx/core/content/pm/ShortcutManagerCompat.html +[4]: https://developer.android.com/reference/androidx/core/content/pm/ShortcutInfoCompat.Builder.html + ]]> + </intro> + </metadata> +</sample> |