Suppport receiving 'share' actions from other apps.

This commit is contained in:
Moxie Marlinspike 2013-02-02 20:37:40 -08:00
parent 6bdb0e2d66
commit 288e2b5572
3 changed files with 89 additions and 36 deletions

View File

@ -53,6 +53,14 @@
<data android:scheme="smsto" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="audio/*" />
<data android:mimeType="image/*" />
<data android:mimeType="text/*" />
</intent-filter>
</activity>
<activity android:name=".ConversationActivity"

View File

@ -44,11 +44,6 @@ import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import org.thoughtcrime.securesms.components.RecipientsPanel;
import org.thoughtcrime.securesms.crypto.AuthenticityCalculator;
import org.thoughtcrime.securesms.crypto.KeyExchangeInitiator;
@ -74,6 +69,11 @@ import org.thoughtcrime.securesms.util.MemoryCleaner;
import ws.com.google.android.mms.MmsException;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
@ -89,10 +89,17 @@ public class ConversationActivity extends SherlockFragmentActivity
implements ConversationFragment.ConversationFragmentListener
{
private static final int PICK_CONTACT = 1;
private static final int PICK_IMAGE = 2;
private static final int PICK_VIDEO = 3;
private static final int PICK_AUDIO = 4;
public static final String RECIPIENTS_EXTRA = "recipients";
public static final String THREAD_ID_EXTRA = "thread_id";
public static final String MASTER_SECRET_EXTRA = "master_secret";
public static final String DRAFT_TEXT_EXTRA = "draft_text";
public static final String DRAFT_IMAGE_EXTRA = "draft_image";
public static final String DRAFT_AUDIO_EXTRA = "draft_audio";
private static final int PICK_CONTACT = 1;
private static final int PICK_IMAGE = 2;
private static final int PICK_VIDEO = 3;
private static final int PICK_AUDIO = 4;
private MasterSecret masterSecret;
private RecipientsPanel recipientsPanel;
@ -121,6 +128,7 @@ public class ConversationActivity extends SherlockFragmentActivity
initializeReceivers();
initializeResources();
initializeDraft();
initializeTitleBar();
}
@ -396,6 +404,16 @@ public class ConversationActivity extends SherlockFragmentActivity
this.invalidateOptionsMenu();
}
private void initializeDraft() {
String draftText = getIntent().getStringExtra(DRAFT_TEXT_EXTRA);
Uri draftImage = getIntent().getParcelableExtra(DRAFT_IMAGE_EXTRA);
Uri draftAudio = getIntent().getParcelableExtra(DRAFT_AUDIO_EXTRA);
if (draftText != null) composeText.setText(draftText);
if (draftImage != null) addAttachmentImage(draftImage);
if (draftAudio != null) addAttachmentAudio(draftAudio);
}
private void initializeSecurity() {
if (isSingleConversation() &&
KeyUtil.isSessionFor(this, getRecipients().getPrimaryRecipient()))
@ -663,6 +681,7 @@ public class ConversationActivity extends SherlockFragmentActivity
// Listeners
private class AddRecipientButtonListener implements OnClickListener {
@Override
public void onClick(View v) {
Intent intent = new Intent(ConversationActivity.this, ContactSelectionActivity.class);
startActivityForResult(intent, PICK_CONTACT);
@ -670,12 +689,14 @@ public class ConversationActivity extends SherlockFragmentActivity
};
private class AttachmentTypeListener implements DialogInterface.OnClickListener {
@Override
public void onClick(DialogInterface dialog, int which) {
addAttachment(attachmentAdapter.buttonToCommand(which));
}
}
private class RecipientsPanelChangeListener implements RecipientsPanel.RecipientsPanelChangedListener {
@Override
public void onRecipientsPanelUpdate(Recipients recipients) {
initializeSecurity();
initializeTitleBar();
@ -684,10 +705,12 @@ public class ConversationActivity extends SherlockFragmentActivity
}
private class SendButtonListener implements OnClickListener, TextView.OnEditorActionListener {
@Override
public void onClick(View v) {
sendMessage(false);
}
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEND) {
sendButton.performClick();
@ -699,15 +722,19 @@ public class ConversationActivity extends SherlockFragmentActivity
};
private class OnTextChangedListener implements TextWatcher {
@Override
public void afterTextChanged(Editable s) {
calculateCharactersRemaining();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before,int count) {}
}
private class ComposeKeyPressedListener implements OnKeyListener {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (keyCode == KeyEvent.KEYCODE_ENTER) {

View File

@ -9,6 +9,7 @@ import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
@ -17,11 +18,6 @@ import android.provider.ContactsContract;
import android.util.Log;
import android.view.WindowManager;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import org.thoughtcrime.securesms.ApplicationExportManager.ApplicationExportListener;
import org.thoughtcrime.securesms.crypto.DecryptingQueue;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
@ -35,6 +31,11 @@ import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.service.SendReceiveService;
import org.thoughtcrime.securesms.util.MemoryCleaner;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
public class ConversationListActivity extends SherlockFragmentActivity
implements ConversationListFragment.ConversationSelectedListener
{
@ -63,7 +64,6 @@ public class ConversationListActivity extends SherlockFragmentActivity
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.w("SecureSMS", "Got onNewIntent...");
createConversationIfNecessary(intent);
}
@ -72,7 +72,6 @@ public class ConversationListActivity extends SherlockFragmentActivity
super.onPause();
if (newKeyReceiver != null) {
Log.w("ConversationListActivity", "Unregistering receiver...");
unregisterReceiver(newKeyReceiver);
newKeyReceiver = null;
}
@ -81,7 +80,6 @@ public class ConversationListActivity extends SherlockFragmentActivity
@Override
public void onResume() {
super.onResume();
Log.w("ConversationListActivity", "onResume called...");
clearNotifications();
initializeKeyCachingServiceRegistration();
@ -126,12 +124,12 @@ public class ConversationListActivity extends SherlockFragmentActivity
super.onOptionsItemSelected(item);
switch (item.getItemId()) {
case R.id.menu_new_message: createConversation(-1, null); return true;
case R.id.menu_unlock: promptForPassphrase(); return true;
case R.id.menu_settings: handleDisplaySettings(); return true;
case R.id.menu_export: handleExportDatabase(); return true;
case R.id.menu_import: handleImportDatabase(); return true;
case R.id.menu_clear_passphrase: handleClearPassphrase(); return true;
case R.id.menu_new_message: createConversation(-1, null, null, null, null); return true;
case R.id.menu_unlock: promptForPassphrase(); return true;
case R.id.menu_settings: handleDisplaySettings(); return true;
case R.id.menu_export: handleExportDatabase(); return true;
case R.id.menu_import: handleImportDatabase(); return true;
case R.id.menu_clear_passphrase: handleClearPassphrase(); return true;
}
return false;
@ -139,21 +137,25 @@ public class ConversationListActivity extends SherlockFragmentActivity
@Override
public void onCreateConversation(long threadId, Recipients recipients) {
createConversation(threadId, recipients);
createConversation(threadId, recipients, null, null, null);
}
private void createConversation(long threadId, Recipients recipients) {
private void createConversation(long threadId, Recipients recipients,
String text, Uri imageUri, Uri audioUri)
{
if (this.masterSecret == null) {
promptForPassphrase();
return;
}
Log.w("ConversationListActivity", "Creating conversation: " + threadId);
Intent intent = new Intent(this, ConversationActivity.class);
intent.putExtra("recipients", recipients);
intent.putExtra("thread_id", threadId);
intent.putExtra("master_secret", masterSecret);
intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients);
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
intent.putExtra(ConversationActivity.MASTER_SECRET_EXTRA, masterSecret);
intent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, text);
intent.putExtra(ConversationActivity.DRAFT_IMAGE_EXTRA, imageUri);
intent.putExtra(ConversationActivity.DRAFT_AUDIO_EXTRA, audioUri);
startActivity(intent);
}
@ -322,27 +324,39 @@ public class ConversationListActivity extends SherlockFragmentActivity
}
private void createConversationIfNecessary(Intent intent) {
Log.w("ConversationListActivity", "createConversationIfNecessary called");
long thread = intent.getLongExtra("thread_id", -1L);
String type = intent.getType();
Recipients recipients = null;
String draftText = null;
Uri draftImage = null;
Uri draftAudio = null;
if (intent.getAction() != null && intent.getAction().equals("android.intent.action.SENDTO")) {
Log.w("ConversationListActivity", "Intent has sendto action...");
if (Intent.ACTION_SENDTO.equals(intent.getAction())) {
try {
recipients = RecipientFactory.getRecipientsFromString(this, intent.getData().getSchemeSpecificPart(), false);
thread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipients);
} catch (RecipientFormattingException rfe) {
recipients = null;
}
} else if (Intent.ACTION_SEND.equals(intent.getAction())) {
if ("text/plain".equals(type)) {
draftText = intent.getStringExtra(Intent.EXTRA_TEXT);
} else if (type.startsWith("image/")) {
draftImage = intent.getParcelableExtra(Intent.EXTRA_STREAM);
} else if (type.startsWith("audio/")) {
draftAudio = intent.getParcelableExtra(Intent.EXTRA_STREAM);
}
} else {
recipients = intent.getParcelableExtra("recipients");
}
if (recipients != null) {
Log.w("ConversationListActivity", "Creating conversation: " + thread + " , " + recipients);
createConversation(thread, recipients);
if (recipients != null || Intent.ACTION_SEND.equals(intent.getAction())) {
createConversation(thread, recipients, draftText, draftImage, draftAudio);
intent.putExtra("thread_id", -1L);
intent.putExtra("recipients", (Parcelable)null);
intent.putExtra(Intent.EXTRA_TEXT, (String)null);
intent.putExtra(Intent.EXTRA_STREAM, (Parcelable)null);
intent.setAction(null);
}
}
@ -360,6 +374,7 @@ public class ConversationListActivity extends SherlockFragmentActivity
}
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
KeyCachingService keyCachingService = ((KeyCachingService.KeyCachingBinder)service).getService();
MasterSecret masterSecret = keyCachingService.getMasterSecret();
@ -379,16 +394,19 @@ public class ConversationListActivity extends SherlockFragmentActivity
}
}
@Override
public void onServiceDisconnected(ComponentName name) {}
};
private class IdentityKeyInitializer implements Runnable {
@Override
public void run() {
IdentityKeyUtil.generateIdentityKeys(ConversationListActivity.this, masterSecret);
}
}
private class AsymmetricMasteSecretInitializer implements Runnable {
@Override
public void run() {
MasterSecretUtil.generateAsymmetricMasterSecret(ConversationListActivity.this, masterSecret);
}