Clean up shortcut code.
@ -214,7 +214,6 @@
|
||||
android:windowSoftInputMode="stateUnchanged"
|
||||
android:launchMode="singleTask"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
||||
android:exported="true"
|
||||
android:parentActivityName=".ConversationListActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
@ -413,6 +412,11 @@
|
||||
android:theme="@style/TextSecure.LightNoActionBar"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
|
||||
<activity android:name=".ShortcutLauncherActivity"
|
||||
android:theme="@style/TextSecure.LightNoActionBar"
|
||||
android:exported="true"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
|
||||
<service android:enabled="true" android:name="org.thoughtcrime.securesms.service.WebRtcCallService"/>
|
||||
<service android:enabled="true" android:name=".service.ApplicationMigrationService"/>
|
||||
<service android:enabled="true" android:exported="false" android:name=".service.KeyCachingService"/>
|
||||
|
BIN
res/mipmap-hdpi/ic_group_shortcut.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
res/mipmap-hdpi/ic_person_shortcut.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
res/mipmap-mdpi/ic_group_shortcut.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
res/mipmap-mdpi/ic_person_shortcut.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
res/mipmap-xhdpi/ic_group_shortcut.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
res/mipmap-xhdpi/ic_person_shortcut.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
res/mipmap-xxhdpi/ic_group_shortcut.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
res/mipmap-xxhdpi/ic_person_shortcut.png
Normal file
After Width: | Height: | Size: 9.3 KiB |
BIN
res/mipmap-xxxhdpi/ic_group_shortcut.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
res/mipmap-xxxhdpi/ic_person_shortcut.png
Normal file
After Width: | Height: | Size: 13 KiB |
@ -1232,6 +1232,7 @@
|
||||
<string name="conversation__menu_leave_group">Leave group</string>
|
||||
<string name="conversation__menu_view_all_media">All media</string>
|
||||
<string name="conversation__menu_conversation_settings">Conversation settings</string>
|
||||
<string name="conversation__menu_add_shortcut">Add to home screen</string>
|
||||
|
||||
<!-- conversation_popup -->
|
||||
<string name="conversation_popup__menu_expand_popup">Expand popup</string>
|
||||
@ -1390,7 +1391,6 @@
|
||||
<string name="prompt_passphrase_activity__signal_is_locked">Signal is locked</string>
|
||||
<string name="prompt_passphrase_activity__tap_to_unlock">TAP TO UNLOCK</string>
|
||||
<string name="RegistrationLockDialog_reminder">Reminder:</string>
|
||||
<string name="conversation__menu_add_shortcut">Add to home screen</string>
|
||||
<string name="recipient_preferences__about">About</string>
|
||||
<!-- EOF -->
|
||||
|
||||
|
@ -26,6 +26,7 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
@ -39,6 +40,9 @@ import android.provider.ContactsContract;
|
||||
import android.provider.Telephony;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.pm.ShortcutInfoCompat;
|
||||
import android.support.v4.content.pm.ShortcutManagerCompat;
|
||||
import android.support.v4.graphics.drawable.IconCompat;
|
||||
import android.support.v4.view.MenuItemCompat;
|
||||
import android.support.v4.view.WindowCompat;
|
||||
import android.support.v7.app.ActionBar;
|
||||
@ -781,32 +785,47 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
private void handleAddShortcut() {
|
||||
Log.i(TAG, "Creating home screen shortcut for recipient " + recipient.getAddress());
|
||||
|
||||
Intent launchIntent = new Intent(getApplicationContext(), ConversationActivity.class);
|
||||
new AsyncTask<Void, Void, IconCompat>() {
|
||||
|
||||
launchIntent.putExtra(ADDRESS_EXTRA, recipient.getAddress().serialize());
|
||||
launchIntent.putExtra(TEXT_EXTRA, getIntent().getStringExtra(ConversationActivity.TEXT_EXTRA));
|
||||
launchIntent.setDataAndType(getIntent().getData(), getIntent().getType());
|
||||
@Override
|
||||
protected IconCompat doInBackground(Void... voids) {
|
||||
Context context = getApplicationContext();
|
||||
IconCompat icon = null;
|
||||
|
||||
long existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient);
|
||||
if (recipient.getContactPhoto() != null) {
|
||||
try {
|
||||
icon = IconCompat.createWithAdaptiveBitmap(BitmapFactory.decodeStream(recipient.getContactPhoto().openInputStream(context)));
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, "Failed to decode contact photo during shortcut creation. Falling back to generic icon.", e);
|
||||
}
|
||||
}
|
||||
|
||||
launchIntent.putExtra(ConversationActivity.THREAD_ID_EXTRA, existingThread);
|
||||
launchIntent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
|
||||
if (icon == null) {
|
||||
icon = IconCompat.createWithResource(context, recipient.isGroupRecipient() ? R.mipmap.ic_group_shortcut
|
||||
: R.mipmap.ic_person_shortcut);
|
||||
}
|
||||
|
||||
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
return icon;
|
||||
}
|
||||
|
||||
Intent intent = new Intent();
|
||||
final String name = Optional.fromNullable(recipient.getProfileName())
|
||||
.or(Optional.fromNullable(recipient.getName()))
|
||||
@Override
|
||||
protected void onPostExecute(IconCompat icon) {
|
||||
Context context = getApplicationContext();
|
||||
String name = Optional.fromNullable(recipient.getName())
|
||||
.or(Optional.fromNullable(recipient.getProfileName()))
|
||||
.or(recipient.toShortString());
|
||||
// these constants are deprecated but their replacement (ShortcutManager) is available only from API level 25
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, launchIntent);
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(getApplicationContext(), R.mipmap.ic_launcher));
|
||||
intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
|
||||
|
||||
getApplicationContext().sendBroadcast(intent);
|
||||
Toast.makeText(this, getString(R.string.ConversationActivity_added_to_home_screen), Toast.LENGTH_LONG).show();
|
||||
ShortcutInfoCompat shortcutInfo = new ShortcutInfoCompat.Builder(context, recipient.getAddress().serialize() + '-' + System.currentTimeMillis())
|
||||
.setShortLabel(name)
|
||||
.setIcon(icon)
|
||||
.setIntent(ShortcutLauncherActivity.createIntent(context, recipient.getAddress()))
|
||||
.build();
|
||||
|
||||
if (ShortcutManagerCompat.requestPinShortcut(context, shortcutInfo, null)) {
|
||||
Toast.makeText(context, getString(R.string.ConversationActivity_added_to_home_screen), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
private void handleLeavePushGroup() {
|
||||
@ -1380,7 +1399,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
private void initializeResources() {
|
||||
if (recipient != null) recipient.removeListener(this);
|
||||
recipient = getRecipientFromExtras(getIntent(), this);
|
||||
|
||||
recipient = Recipient.from(this, getIntent().getParcelableExtra(ADDRESS_EXTRA), true);
|
||||
threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1);
|
||||
archived = getIntent().getBooleanExtra(IS_ARCHIVED_EXTRA, false);
|
||||
distributionType = getIntent().getIntExtra(DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
|
||||
@ -1395,26 +1415,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
recipient.addListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the Recipient instance from the extras contained in the intent.
|
||||
*
|
||||
* This can be passed in two ways:
|
||||
*
|
||||
* - If the intent was started from inside the app, the address is a parcelable Address instance.
|
||||
* - If it was launched from the home screen then it is a serialised (stringified) form of the Address, as home screen
|
||||
* shortcuts cannot contain instances of Address (see BadParcelableException).
|
||||
*/
|
||||
static Recipient getRecipientFromExtras(@NonNull Intent intent, @NonNull Context context) {
|
||||
Address address;
|
||||
final Address parcelableAddress = intent.getParcelableExtra(ADDRESS_EXTRA);
|
||||
if(parcelableAddress != null) {
|
||||
address = parcelableAddress;
|
||||
} else {
|
||||
address = Address.fromSerialized((String) intent.getExtras().get(ADDRESS_EXTRA));
|
||||
}
|
||||
return Recipient.from(context, address, true);
|
||||
}
|
||||
|
||||
private void initializeProfiles() {
|
||||
if (!isSecureText) {
|
||||
Log.i(TAG, "SMS contact, no profile fetch needed.");
|
||||
|
@ -206,7 +206,7 @@ public class ConversationFragment extends Fragment
|
||||
}
|
||||
|
||||
private void initializeResources() {
|
||||
this.recipient = ConversationActivity.getRecipientFromExtras(getActivity().getIntent(), getActivity());
|
||||
this.recipient = Recipient.from(getActivity(), getActivity().getIntent().getParcelableExtra(ConversationActivity.ADDRESS_EXTRA), true);
|
||||
this.threadId = this.getActivity().getIntent().getLongExtra(ConversationActivity.THREAD_ID_EXTRA, -1);
|
||||
this.lastSeen = this.getActivity().getIntent().getLongExtra(ConversationActivity.LAST_SEEN_EXTRA, -1);
|
||||
this.startingPosition = this.getActivity().getIntent().getIntExtra(ConversationActivity.STARTING_POSITION_EXTRA, -1);
|
||||
|
42
src/org/thoughtcrime/securesms/ShortcutLauncherActivity.java
Normal file
@ -0,0 +1,42 @@
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.TaskStackBuilder;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.CommunicationActions;
|
||||
|
||||
public class ShortcutLauncherActivity extends AppCompatActivity {
|
||||
|
||||
private static final String KEY_SERIALIZED_ADDRESS = "serialized_address";
|
||||
|
||||
public static Intent createIntent(@NonNull Context context, @NonNull Address address) {
|
||||
Intent intent = new Intent(context, ShortcutLauncherActivity.class);
|
||||
intent.setAction(Intent.ACTION_MAIN);
|
||||
intent.putExtra(KEY_SERIALIZED_ADDRESS, address.serialize());
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
String serializedAddress = getIntent().getStringExtra(KEY_SERIALIZED_ADDRESS);
|
||||
Address address = Address.fromSerialized(serializedAddress);
|
||||
Recipient recipient = Recipient.from(this, address, true);
|
||||
TaskStackBuilder backStack = TaskStackBuilder.create(this)
|
||||
.addNextIntent(new Intent(this, ConversationListActivity.class));
|
||||
|
||||
CommunicationActions.startConversation(this, recipient, null, backStack);
|
||||
finish();
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@ import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.TaskStackBuilder;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.thoughtcrime.securesms.ConversationActivity;
|
||||
@ -43,9 +44,14 @@ public class CommunicationActions {
|
||||
.execute();
|
||||
}
|
||||
|
||||
public static void startConversation(@NonNull Context context, @NonNull Recipient recipient, @Nullable String text) {
|
||||
startConversation(context, recipient, text, null);
|
||||
}
|
||||
|
||||
public static void startConversation(@NonNull Context context,
|
||||
@NonNull Recipient recipient,
|
||||
@Nullable String text)
|
||||
@Nullable String text,
|
||||
@Nullable TaskStackBuilder backStack)
|
||||
{
|
||||
new AsyncTask<Void, Void, Long>() {
|
||||
@Override
|
||||
@ -64,8 +70,13 @@ public class CommunicationActions {
|
||||
intent.putExtra(ConversationActivity.TEXT_EXTRA, text);
|
||||
}
|
||||
|
||||
if (backStack != null) {
|
||||
backStack.addNextIntent(intent);
|
||||
backStack.startActivities();
|
||||
} else {
|
||||
context.startActivity(intent);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
|