├── .google └── packaging.yaml ├── Application ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── example │ │ └── android │ │ └── directshare │ │ ├── Contact.java │ │ ├── ContactViewBinder.java │ │ ├── MainActivity.java │ │ ├── SampleChooserTargetService.java │ │ ├── SelectContactActivity.java │ │ └── SendMessageActivity.java │ └── res │ ├── drawable-hdpi │ └── tile.9.png │ ├── layout │ ├── contact.xml │ ├── main.xml │ ├── select_contact.xml │ └── send_message.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── logo_avatar.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── logo_avatar.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── logo_avatar.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── logo_avatar.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── logo_avatar.png │ ├── values-sw600dp │ ├── template-dimens.xml │ └── template-styles.xml │ ├── values-v11 │ └── template-styles.xml │ ├── values-v21 │ ├── base-colors.xml │ └── base-template-styles.xml │ └── values │ ├── base-strings.xml │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ ├── styles.xml │ ├── template-dimens.xml │ └── template-styles.xml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screenshots ├── 1-main.png ├── 2-intent.png ├── 3-message.png └── icon-web.png └── settings.gradle /.google/packaging.yaml: -------------------------------------------------------------------------------- 1 | 2 | # GOOGLE SAMPLE PACKAGING DATA 3 | # 4 | # This file is used by Google as part of our samples packaging process. 5 | # End users may safely ignore this file. It has no relevance to other systems. 6 | --- 7 | status: PUBLISHED 8 | technologies: [Android] 9 | categories: [Content] 10 | languages: [Java] 11 | solutions: [Mobile] 12 | github: android-DirectShare 13 | level: INTERMEDIATE 14 | icon: screenshots/icon-web.png 15 | apiRefs: 16 | - android:android.service.chooser.ChooserTargetService 17 | - android:android.service.chooser.ChooserTarget 18 | license: apache2 19 | -------------------------------------------------------------------------------- /Application/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | buildscript { 3 | repositories { 4 | jcenter() 5 | google() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:3.0.1' 10 | } 11 | } 12 | 13 | apply plugin: 'com.android.application' 14 | 15 | repositories { 16 | jcenter() 17 | google() 18 | } 19 | 20 | dependencies { 21 | compile "com.android.support:support-v4:27.0.2" 22 | compile "com.android.support:support-v13:27.0.2" 23 | compile "com.android.support:cardview-v7:27.0.2" 24 | compile "com.android.support:appcompat-v7:27.0.2" 25 | } 26 | 27 | // The sample build uses multiple directories to 28 | // keep boilerplate and common code separate from 29 | // the main sample code. 30 | List dirs = [ 31 | 'main', // main sample code; look here for the interesting stuff. 32 | 'common', // components that are reused by multiple samples 33 | 'template'] // boilerplate code that is generated by the sample template process 34 | 35 | android { 36 | compileSdkVersion 27 37 | 38 | buildToolsVersion "27.0.2" 39 | 40 | defaultConfig { 41 | minSdkVersion 23 42 | targetSdkVersion 27 43 | } 44 | 45 | compileOptions { 46 | sourceCompatibility JavaVersion.VERSION_1_7 47 | targetCompatibility JavaVersion.VERSION_1_7 48 | } 49 | 50 | sourceSets { 51 | main { 52 | dirs.each { dir -> 53 | java.srcDirs "src/${dir}/java" 54 | res.srcDirs "src/${dir}/res" 55 | } 56 | } 57 | androidTest.setRoot('tests') 58 | androidTest.java.srcDirs = ['tests/src'] 59 | 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /Application/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 21 | 22 | 27 | 28 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 41 | 42 | 43 | 44 | 45 | 46 | 49 | 50 | 51 | 55 | 56 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /Application/src/main/java/com/example/android/directshare/Contact.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.android.directshare; 18 | 19 | /** 20 | * Provides the list of dummy contacts. This sample implements this as constants, but real-life apps 21 | * should use a database and such. 22 | */ 23 | public class Contact { 24 | 25 | /** 26 | * The list of dummy contacts. 27 | */ 28 | public static final Contact[] CONTACTS = { 29 | new Contact("Tereasa"), 30 | new Contact("Chang"), 31 | new Contact("Kory"), 32 | new Contact("Clare"), 33 | new Contact("Landon"), 34 | new Contact("Kyle"), 35 | new Contact("Deana"), 36 | new Contact("Daria"), 37 | new Contact("Melisa"), 38 | new Contact("Sammie"), 39 | }; 40 | 41 | /** 42 | * The contact ID. 43 | */ 44 | public static final String ID = "contact_id"; 45 | 46 | /** 47 | * Representative invalid contact ID. 48 | */ 49 | public static final int INVALID_ID = -1; 50 | 51 | /** 52 | * The name of this contact. 53 | */ 54 | private final String mName; 55 | 56 | /** 57 | * Instantiates a new {@link Contact}. 58 | * 59 | * @param name The name of the contact. 60 | */ 61 | public Contact(String name) { 62 | mName = name; 63 | } 64 | 65 | /** 66 | * Finds a {@link Contact} specified by a contact ID. 67 | * 68 | * @param id The contact ID. This needs to be a valid ID. 69 | * @return A {@link Contact} 70 | */ 71 | public static Contact byId(int id) { 72 | return CONTACTS[id]; 73 | } 74 | 75 | /** 76 | * Gets the name of this contact. 77 | * 78 | * @return The name of this contact. 79 | */ 80 | public String getName() { 81 | return mName; 82 | } 83 | 84 | /** 85 | * Gets the icon of this contact. 86 | * 87 | * @return The icon. 88 | */ 89 | public int getIcon() { 90 | return R.mipmap.logo_avatar; 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /Application/src/main/java/com/example/android/directshare/ContactViewBinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.android.directshare; 18 | 19 | import android.widget.TextView; 20 | 21 | /** 22 | * A simple utility to bind a {@link TextView} with a {@link Contact}. 23 | */ 24 | public class ContactViewBinder { 25 | 26 | /** 27 | * Binds the {@code textView} with the specified {@code contact}. 28 | * 29 | * @param contact The contact. 30 | * @param textView The TextView. 31 | */ 32 | public static void bind(Contact contact, TextView textView) { 33 | textView.setText(contact.getName()); 34 | textView.setCompoundDrawablesRelativeWithIntrinsicBounds(contact.getIcon(), 0, 0, 0); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /Application/src/main/java/com/example/android/directshare/MainActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.android.directshare; 18 | 19 | import android.app.Activity; 20 | import android.content.Intent; 21 | import android.os.Bundle; 22 | import android.view.View; 23 | import android.widget.EditText; 24 | import android.widget.Toolbar; 25 | 26 | /** 27 | * Provides the landing screen of this sample. There is nothing particularly interesting here. All 28 | * the codes related to the Direct Share feature are in {@link SampleChooserTargetService}. 29 | */ 30 | public class MainActivity extends Activity { 31 | 32 | private EditText mEditBody; 33 | 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | setContentView(R.layout.main); 38 | setActionBar((Toolbar) findViewById(R.id.toolbar)); 39 | mEditBody = (EditText) findViewById(R.id.body); 40 | findViewById(R.id.share).setOnClickListener(mOnClickListener); 41 | } 42 | 43 | private View.OnClickListener mOnClickListener = new View.OnClickListener() { 44 | @Override 45 | public void onClick(View v) { 46 | switch (v.getId()) { 47 | case R.id.share: 48 | share(); 49 | break; 50 | } 51 | } 52 | }; 53 | 54 | /** 55 | * Emits a sample share {@link Intent}. 56 | */ 57 | private void share() { 58 | Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND); 59 | sharingIntent.setType("text/plain"); 60 | sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, mEditBody.getText().toString()); 61 | startActivity(Intent.createChooser(sharingIntent, getString(R.string.send_intent_title))); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /Application/src/main/java/com/example/android/directshare/SampleChooserTargetService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.android.directshare; 18 | 19 | import android.content.ComponentName; 20 | import android.content.IntentFilter; 21 | import android.graphics.drawable.Icon; 22 | import android.os.Bundle; 23 | import android.service.chooser.ChooserTarget; 24 | import android.service.chooser.ChooserTargetService; 25 | 26 | import java.util.ArrayList; 27 | import java.util.List; 28 | 29 | /** 30 | * Provides the Direct Share items to the system. 31 | */ 32 | public class SampleChooserTargetService extends ChooserTargetService { 33 | 34 | @Override 35 | public List onGetChooserTargets(ComponentName targetActivityName, 36 | IntentFilter matchedFilter) { 37 | ComponentName componentName = new ComponentName(getPackageName(), 38 | SendMessageActivity.class.getCanonicalName()); 39 | // The list of Direct Share items. The system will show the items the way they are sorted 40 | // in this list. 41 | ArrayList targets = new ArrayList<>(); 42 | for (int i = 0; i < Contact.CONTACTS.length; ++i) { 43 | Contact contact = Contact.byId(i); 44 | Bundle extras = new Bundle(); 45 | extras.putInt(Contact.ID, i); 46 | targets.add(new ChooserTarget( 47 | // The name of this target. 48 | contact.getName(), 49 | // The icon to represent this target. 50 | Icon.createWithResource(this, contact.getIcon()), 51 | // The ranking score for this target (0.0-1.0); the system will omit items with 52 | // low scores when there are too many Direct Share items. 53 | 0.5f, 54 | // The name of the component to be launched if this target is chosen. 55 | componentName, 56 | // The extra values here will be merged into the Intent when this target is 57 | // chosen. 58 | extras)); 59 | } 60 | return targets; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /Application/src/main/java/com/example/android/directshare/SelectContactActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.android.directshare; 18 | 19 | import android.app.Activity; 20 | import android.content.Intent; 21 | import android.os.Bundle; 22 | import android.view.LayoutInflater; 23 | import android.view.View; 24 | import android.view.ViewGroup; 25 | import android.widget.AdapterView; 26 | import android.widget.BaseAdapter; 27 | import android.widget.ListAdapter; 28 | import android.widget.ListView; 29 | import android.widget.TextView; 30 | 31 | /** 32 | * The dialog for selecting a contact to share the text with. This dialog is shown when the user 33 | * taps on this sample's icon rather than any of the Direct Share contacts. 34 | */ 35 | public class SelectContactActivity extends Activity { 36 | 37 | /** 38 | * The action string for Intents. 39 | */ 40 | public static final String ACTION_SELECT_CONTACT 41 | = "com.example.android.directshare.intent.action.SELECT_CONTACT"; 42 | 43 | @Override 44 | protected void onCreate(Bundle savedInstanceState) { 45 | super.onCreate(savedInstanceState); 46 | setContentView(R.layout.select_contact); 47 | Intent intent = getIntent(); 48 | if (!ACTION_SELECT_CONTACT.equals(intent.getAction())) { 49 | finish(); 50 | return; 51 | } 52 | // Set up the list of contacts 53 | ListView list = (ListView) findViewById(R.id.list); 54 | list.setAdapter(mAdapter); 55 | list.setOnItemClickListener(mOnItemClickListener); 56 | } 57 | 58 | private final ListAdapter mAdapter = new BaseAdapter() { 59 | @Override 60 | public int getCount() { 61 | return Contact.CONTACTS.length; 62 | } 63 | 64 | @Override 65 | public Object getItem(int i) { 66 | return Contact.byId(i); 67 | } 68 | 69 | @Override 70 | public long getItemId(int i) { 71 | return i; 72 | } 73 | 74 | @Override 75 | public View getView(int i, View view, ViewGroup parent) { 76 | if (view == null) { 77 | view = LayoutInflater.from(parent.getContext()).inflate(R.layout.contact, parent, 78 | false); 79 | } 80 | TextView textView = (TextView) view; 81 | Contact contact = (Contact) getItem(i); 82 | ContactViewBinder.bind(contact, textView); 83 | return textView; 84 | } 85 | }; 86 | 87 | private final AdapterView.OnItemClickListener mOnItemClickListener 88 | = new AdapterView.OnItemClickListener() { 89 | @Override 90 | public void onItemClick(AdapterView adapterView, View view, int i, long l) { 91 | Intent data = new Intent(); 92 | data.putExtra(Contact.ID, i); 93 | setResult(RESULT_OK, data); 94 | finish(); 95 | } 96 | }; 97 | 98 | } 99 | -------------------------------------------------------------------------------- /Application/src/main/java/com/example/android/directshare/SendMessageActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.android.directshare; 18 | 19 | import android.app.Activity; 20 | import android.content.Intent; 21 | import android.os.Bundle; 22 | import android.view.View; 23 | import android.widget.TextView; 24 | import android.widget.Toast; 25 | 26 | /** 27 | * Provides the UI for sharing a text with a {@link Contact}. 28 | */ 29 | public class SendMessageActivity extends Activity { 30 | 31 | /** 32 | * The request code for {@link SelectContactActivity}. This is used when the user doesn't select 33 | * any of Direct Share icons. 34 | */ 35 | private static final int REQUEST_SELECT_CONTACT = 1; 36 | 37 | /** 38 | * The text to share. 39 | */ 40 | private String mBody; 41 | 42 | /** 43 | * The ID of the contact to share the text with. 44 | */ 45 | private int mContactId; 46 | 47 | // View references. 48 | private TextView mTextContactName; 49 | private TextView mTextMessageBody; 50 | 51 | @Override 52 | protected void onCreate(Bundle savedInstanceState) { 53 | super.onCreate(savedInstanceState); 54 | setContentView(R.layout.send_message); 55 | setTitle(R.string.sending_message); 56 | // View references. 57 | mTextContactName = (TextView) findViewById(R.id.contact_name); 58 | mTextMessageBody = (TextView) findViewById(R.id.message_body); 59 | // Resolve the share Intent. 60 | boolean resolved = resolveIntent(getIntent()); 61 | if (!resolved) { 62 | finish(); 63 | return; 64 | } 65 | // Bind event handlers. 66 | findViewById(R.id.send).setOnClickListener(mOnClickListener); 67 | // Set up the UI. 68 | prepareUi(); 69 | // The contact ID will not be passed on when the user clicks on the app icon rather than any 70 | // of the Direct Share icons. In this case, we show another dialog for selecting a contact. 71 | if (mContactId == Contact.INVALID_ID) { 72 | selectContact(); 73 | } 74 | } 75 | 76 | @Override 77 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 78 | switch (requestCode) { 79 | case REQUEST_SELECT_CONTACT: 80 | if (resultCode == RESULT_OK) { 81 | mContactId = data.getIntExtra(Contact.ID, Contact.INVALID_ID); 82 | } 83 | // Give up sharing the send_message if the user didn't choose a contact. 84 | if (mContactId == Contact.INVALID_ID) { 85 | finish(); 86 | return; 87 | } 88 | prepareUi(); 89 | break; 90 | default: 91 | super.onActivityResult(requestCode, resultCode, data); 92 | } 93 | } 94 | 95 | /** 96 | * Resolves the passed {@link Intent}. This method can only resolve intents for sharing a plain 97 | * text. {@link #mBody} and {@link #mContactId} are modified accordingly. 98 | * 99 | * @param intent The {@link Intent}. 100 | * @return True if the {@code intent} is resolved properly. 101 | */ 102 | private boolean resolveIntent(Intent intent) { 103 | if (Intent.ACTION_SEND.equals(intent.getAction()) && 104 | "text/plain".equals(intent.getType())) { 105 | mBody = intent.getStringExtra(Intent.EXTRA_TEXT); 106 | mContactId = intent.getIntExtra(Contact.ID, Contact.INVALID_ID); 107 | return true; 108 | } 109 | return false; 110 | } 111 | 112 | /** 113 | * Sets up the UI. 114 | */ 115 | private void prepareUi() { 116 | if (mContactId != Contact.INVALID_ID) { 117 | Contact contact = Contact.byId(mContactId); 118 | ContactViewBinder.bind(contact, mTextContactName); 119 | } 120 | mTextMessageBody.setText(mBody); 121 | } 122 | 123 | /** 124 | * Delegates selection of a {@Contact} to {@link SelectContactActivity}. 125 | */ 126 | private void selectContact() { 127 | Intent intent = new Intent(this, SelectContactActivity.class); 128 | intent.setAction(SelectContactActivity.ACTION_SELECT_CONTACT); 129 | startActivityForResult(intent, REQUEST_SELECT_CONTACT); 130 | } 131 | 132 | private View.OnClickListener mOnClickListener = new View.OnClickListener() { 133 | @Override 134 | public void onClick(View view) { 135 | switch (view.getId()) { 136 | case R.id.send: 137 | send(); 138 | break; 139 | } 140 | } 141 | }; 142 | 143 | /** 144 | * Pretends to send the text to the contact. This only shows a dummy message. 145 | */ 146 | private void send() { 147 | Toast.makeText(this, 148 | getString(R.string.message_sent, mBody, Contact.byId(mContactId).getName()), 149 | Toast.LENGTH_SHORT).show(); 150 | finish(); 151 | } 152 | 153 | } 154 | -------------------------------------------------------------------------------- /Application/src/main/res/drawable-hdpi/tile.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlearchive/android-DirectShare/1dadebad32775b5af2227502ecc4ab296cd981bd/Application/src/main/res/drawable-hdpi/tile.9.png -------------------------------------------------------------------------------- /Application/src/main/res/layout/contact.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 31 | -------------------------------------------------------------------------------- /Application/src/main/res/layout/main.xml: -------------------------------------------------------------------------------- 1 | 16 | 20 | 21 | 30 | 31 | 37 | 38 | 42 | 43 | 52 | 53 |