mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-18 16:57:46 +00:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e61161767 | ||
|
|
83d281de71 | ||
|
|
28f63cf335 | ||
|
|
f3a3aaca60 | ||
|
|
908e8b8746 | ||
|
|
4573f3cb77 | ||
|
|
d72a3ec669 | ||
|
|
3439657bba | ||
|
|
1ad7912e75 | ||
|
|
30aff82341 | ||
|
|
c54a5b613b | ||
|
|
31ad30b3a5 | ||
|
|
4ccb7ebab6 | ||
|
|
bf69a90b69 | ||
|
|
bf19307916 | ||
|
|
d42c4229fd |
@@ -2,8 +2,8 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="org.thoughtcrime.securesms"
|
||||
android:versionCode="84"
|
||||
android:versionName="2.3.0">
|
||||
android:versionCode="86"
|
||||
android:versionName="2.3.2">
|
||||
|
||||
<permission android:name="org.thoughtcrime.securesms.ACCESS_SECRETS"
|
||||
android:label="Access to TextSecure Secrets"
|
||||
@@ -208,13 +208,14 @@
|
||||
android:clearTaskOnLaunch="true"
|
||||
android:finishOnTaskLaunch="true" />
|
||||
|
||||
<service android:enabled="true" android:name=".service.GcmRegistrationService"/>
|
||||
<activity android:name=".PlayServicesProblemActivity"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
|
||||
<service android:enabled="true" android:name=".service.ApplicationMigrationService"/>
|
||||
<service android:enabled="true" android:name=".service.KeyCachingService"/>
|
||||
<service android:enabled="true" android:name=".service.SendReceiveService"/>
|
||||
<service android:enabled="true" android:name=".service.RegistrationService"/>
|
||||
<service android:enabled="true" android:name=".service.DirectoryRefreshService"/>
|
||||
<service android:enabled="true" android:name=".service.PreKeyService"/>
|
||||
|
||||
<service android:name=".service.QuickResponseService"
|
||||
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
|
||||
|
||||
10
build.gradle
10
build.gradle
@@ -36,8 +36,9 @@ dependencies {
|
||||
compile 'org.w3c:smil:1.0.0'
|
||||
compile 'org.apache.httpcomponents:httpclient-android:4.3.5'
|
||||
compile 'com.github.chrisbanes.photoview:library:1.2.3'
|
||||
compile 'com.android.support:appcompat-v7:21.0.2'
|
||||
compile 'com.android.support:appcompat-v7:20.0.0'
|
||||
compile 'com.madgag.spongycastle:prov:1.51.0.0'
|
||||
compile 'com.google.zxing:android-integration:3.1.0'
|
||||
compile ('com.android.support:support-v4-preferencefragment:1.0.0@aar'){
|
||||
exclude module: 'support-v4'
|
||||
}
|
||||
@@ -60,17 +61,18 @@ dependencyVerification {
|
||||
'org.w3c:smil:085dc40f2bb249651578bfa07499fd08b16ad0886dbe2c4078586a408da62f9b',
|
||||
'org.apache.httpcomponents:httpclient-android:6f56466a9bd0d42934b90bfbfe9977a8b654c058bf44a12bdc2877c4e1f033f1',
|
||||
'com.github.chrisbanes.photoview:library:8b5344e206f125e7ba9d684008f36c4992d03853c57e5814125f88496126e3cc',
|
||||
'com.android.support:appcompat-v7:b760fd3d0b0b0547a1bcef9031b40939f31049ba955f04c8fdc5aa09a25d19e9',
|
||||
'com.android.support:appcompat-v7:736f576ab0b68d27bdf18b1e7931566e6d8254b73965175313e87f8866b91547',
|
||||
'com.madgag.spongycastle:prov:b8c3fec3a59aac1aa04ccf4dad7179351e54ef7672f53f508151b614c131398a',
|
||||
'com.google.zxing:android-integration:89e56aadf1164bd71e57949163c53abf90af368b51669c0d4a47a163335f95c4',
|
||||
'com.android.support:support-v4-preferencefragment:5470f5872514a6226fa1fc6f4e000991f38805691c534cf0bd2778911fc773ad',
|
||||
'com.squareup.dagger:dagger:789aca24537022e49f91fc6444078d9de8f1dd99e1bfb090f18491b186967883',
|
||||
'com.android.support:support-v4:81f2b1c2c94efd5a4ec7fcd97b6cdcd00e87a933905c5c86103c7319eb024572',
|
||||
'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f',
|
||||
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||
'com.google.protobuf:protobuf-java:e0c1c64575c005601725e7c6a02cebf9e1285e888f756b2a1d73ffa8d725cc74',
|
||||
'com.googlecode.libphonenumber:libphonenumber:eba17eae81dd622ea89a00a3a8c025b2f25d342e0d9644c5b62e16f15687c3ab',
|
||||
'org.whispersystems:gson:08f4f7498455d1539c9233e5aac18e9b1805815ef29221572996508eb512fe51',
|
||||
'com.android.support:support-v4:126a4c291f41f75f3fff4968e9d397bc8454cdff4d8f994cbe0524e3bad76e72',
|
||||
'com.android.support:support-annotations:7e37f00e3d932c4d9a6dd84604a99133bb5ae7d81cbd1aee69861fcf2f91e5e9',
|
||||
'com.android.support:support-annotations:1aa96ef0cc4a445bfc2f93ccf762305bc57fa107b12afe9d11f3863ae8a11036',
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.whispersystems.test;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
import org.whispersystems.libaxolotl.DuplicateMessageException;
|
||||
import org.whispersystems.libaxolotl.IdentityKey;
|
||||
import org.whispersystems.libaxolotl.InvalidKeyException;
|
||||
import org.whispersystems.libaxolotl.InvalidKeyIdException;
|
||||
import org.whispersystems.libaxolotl.InvalidMessageException;
|
||||
@@ -24,10 +23,7 @@ import org.whispersystems.libaxolotl.state.AxolotlStore;
|
||||
import org.whispersystems.libaxolotl.state.IdentityKeyStore;
|
||||
import org.whispersystems.libaxolotl.state.PreKeyBundle;
|
||||
import org.whispersystems.libaxolotl.state.PreKeyRecord;
|
||||
import org.whispersystems.libaxolotl.state.PreKeyStore;
|
||||
import org.whispersystems.libaxolotl.state.SessionStore;
|
||||
import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
|
||||
import org.whispersystems.libaxolotl.state.SignedPreKeyStore;
|
||||
import org.whispersystems.libaxolotl.util.Pair;
|
||||
|
||||
import java.util.HashSet;
|
||||
@@ -122,11 +118,11 @@ public class SessionBuilderTest extends AndroidTestCase {
|
||||
AxolotlStore aliceStore = new InMemoryAxolotlStore();
|
||||
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_RECIPIENT_ID, 1);
|
||||
|
||||
AxolotlStore bobStore = new InMemoryAxolotlStore();
|
||||
ECKeyPair bobPreKeyPair = Curve.generateKeyPair();
|
||||
ECKeyPair bobSignedPreKeyPair = Curve.generateKeyPair();
|
||||
byte[] bobSignedPreKeySignature = Curve.calculateSignature(bobStore.getIdentityKeyPair().getPrivateKey(),
|
||||
bobSignedPreKeyPair.getPublicKey().serialize());
|
||||
final AxolotlStore bobStore = new InMemoryAxolotlStore();
|
||||
ECKeyPair bobPreKeyPair = Curve.generateKeyPair();
|
||||
ECKeyPair bobSignedPreKeyPair = Curve.generateKeyPair();
|
||||
byte[] bobSignedPreKeySignature = Curve.calculateSignature(bobStore.getIdentityKeyPair().getPrivateKey(),
|
||||
bobSignedPreKeyPair.getPublicKey().serialize());
|
||||
|
||||
PreKeyBundle bobPreKey = new PreKeyBundle(bobStore.getLocalRegistrationId(), 1,
|
||||
31337, bobPreKeyPair.getPublicKey(),
|
||||
@@ -139,9 +135,9 @@ public class SessionBuilderTest extends AndroidTestCase {
|
||||
assertTrue(aliceStore.containsSession(BOB_RECIPIENT_ID, 1));
|
||||
assertTrue(aliceStore.loadSession(BOB_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 3);
|
||||
|
||||
String originalMessage = "L'homme est condamné à être libre";
|
||||
SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_RECIPIENT_ID, 1);
|
||||
CiphertextMessage outgoingMessage = aliceSessionCipher.encrypt(originalMessage.getBytes());
|
||||
final String originalMessage = "L'homme est condamné à être libre";
|
||||
SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_RECIPIENT_ID, 1);
|
||||
CiphertextMessage outgoingMessage = aliceSessionCipher.encrypt(originalMessage.getBytes());
|
||||
|
||||
assertTrue(outgoingMessage.getType() == CiphertextMessage.PREKEY_TYPE);
|
||||
|
||||
@@ -150,8 +146,13 @@ public class SessionBuilderTest extends AndroidTestCase {
|
||||
bobStore.storeSignedPreKey(22, new SignedPreKeyRecord(22, System.currentTimeMillis(), bobSignedPreKeyPair, bobSignedPreKeySignature));
|
||||
|
||||
SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_RECIPIENT_ID, 1);
|
||||
byte[] plaintext = bobSessionCipher.decrypt(incomingMessage);
|
||||
|
||||
byte[] plaintext = bobSessionCipher.decrypt(incomingMessage, new SessionCipher.DecryptionCallback() {
|
||||
@Override
|
||||
public void handlePlaintext(byte[] plaintext) {
|
||||
assertTrue(originalMessage.equals(new String(plaintext)));
|
||||
assertFalse(bobStore.containsSession(ALICE_RECIPIENT_ID, 1));
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue(bobStore.containsSession(ALICE_RECIPIENT_ID, 1));
|
||||
assertTrue(bobStore.loadSession(ALICE_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 3);
|
||||
|
||||
@@ -19,12 +19,8 @@ import org.whispersystems.libaxolotl.ratchet.AliceAxolotlParameters;
|
||||
import org.whispersystems.libaxolotl.ratchet.BobAxolotlParameters;
|
||||
import org.whispersystems.libaxolotl.ratchet.RatchetingSession;
|
||||
import org.whispersystems.libaxolotl.state.AxolotlStore;
|
||||
import org.whispersystems.libaxolotl.state.IdentityKeyStore;
|
||||
import org.whispersystems.libaxolotl.state.PreKeyStore;
|
||||
import org.whispersystems.libaxolotl.state.SessionRecord;
|
||||
import org.whispersystems.libaxolotl.state.SessionState;
|
||||
import org.whispersystems.libaxolotl.state.SessionStore;
|
||||
import org.whispersystems.libaxolotl.state.SignedPreKeyStore;
|
||||
import org.whispersystems.libaxolotl.util.guava.Optional;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
@@ -138,6 +138,7 @@ public class SessionCipher {
|
||||
* Decrypt a message.
|
||||
*
|
||||
* @param ciphertext The {@link PreKeyWhisperMessage} to decrypt.
|
||||
*
|
||||
* @return The plaintext.
|
||||
* @throws InvalidMessageException if the input is not valid ciphertext.
|
||||
* @throws DuplicateMessageException if the input is a message that has already been received.
|
||||
@@ -147,17 +148,46 @@ public class SessionCipher {
|
||||
* that corresponds to the PreKey ID in the message.
|
||||
* @throws InvalidKeyException when the message is formatted incorrectly.
|
||||
* @throws UntrustedIdentityException when the {@link IdentityKey} of the sender is untrusted.
|
||||
|
||||
*/
|
||||
public byte[] decrypt(PreKeyWhisperMessage ciphertext)
|
||||
throws DuplicateMessageException, LegacyMessageException, InvalidMessageException,
|
||||
InvalidKeyIdException, InvalidKeyException, UntrustedIdentityException
|
||||
{
|
||||
return decrypt(ciphertext, new NullDecryptionCallback());
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt a message.
|
||||
*
|
||||
* @param ciphertext The {@link PreKeyWhisperMessage} to decrypt.
|
||||
* @param callback A callback that is triggered after decryption is complete,
|
||||
* but before the updated session state has been committed to the session
|
||||
* DB. This allows some implementations to store the committed plaintext
|
||||
* to a DB first, in case they are concerned with a crash happening between
|
||||
* the time the session state is updated but before they're able to store
|
||||
* the plaintext to disk.
|
||||
*
|
||||
* @return The plaintext.
|
||||
* @throws InvalidMessageException if the input is not valid ciphertext.
|
||||
* @throws DuplicateMessageException if the input is a message that has already been received.
|
||||
* @throws LegacyMessageException if the input is a message formatted by a protocol version that
|
||||
* is no longer supported.
|
||||
* @throws InvalidKeyIdException when there is no local {@link org.whispersystems.libaxolotl.state.PreKeyRecord}
|
||||
* that corresponds to the PreKey ID in the message.
|
||||
* @throws InvalidKeyException when the message is formatted incorrectly.
|
||||
* @throws UntrustedIdentityException when the {@link IdentityKey} of the sender is untrusted.
|
||||
*/
|
||||
public byte[] decrypt(PreKeyWhisperMessage ciphertext, DecryptionCallback callback)
|
||||
throws DuplicateMessageException, LegacyMessageException, InvalidMessageException,
|
||||
InvalidKeyIdException, InvalidKeyException, UntrustedIdentityException
|
||||
{
|
||||
synchronized (SESSION_LOCK) {
|
||||
SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId);
|
||||
Optional<Integer> unsignedPreKeyId = sessionBuilder.process(sessionRecord, ciphertext);
|
||||
byte[] plaintext = decrypt(sessionRecord, ciphertext.getWhisperMessage());
|
||||
|
||||
callback.handlePlaintext(plaintext);
|
||||
|
||||
sessionStore.storeSession(recipientId, deviceId, sessionRecord);
|
||||
|
||||
if (unsignedPreKeyId.isPresent()) {
|
||||
@@ -168,7 +198,6 @@ public class SessionCipher {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decrypt a message.
|
||||
*
|
||||
@@ -182,6 +211,31 @@ public class SessionCipher {
|
||||
* @throws NoSessionException if there is no established session for this contact.
|
||||
*/
|
||||
public byte[] decrypt(WhisperMessage ciphertext)
|
||||
throws InvalidMessageException, DuplicateMessageException, LegacyMessageException,
|
||||
NoSessionException
|
||||
{
|
||||
return decrypt(ciphertext, new NullDecryptionCallback());
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt a message.
|
||||
*
|
||||
* @param ciphertext The {@link WhisperMessage} to decrypt.
|
||||
* @param callback A callback that is triggered after decryption is complete,
|
||||
* but before the updated session state has been committed to the session
|
||||
* DB. This allows some implementations to store the committed plaintext
|
||||
* to a DB first, in case they are concerned with a crash happening between
|
||||
* the time the session state is updated but before they're able to store
|
||||
* the plaintext to disk.
|
||||
*
|
||||
* @return The plaintext.
|
||||
* @throws InvalidMessageException if the input is not valid ciphertext.
|
||||
* @throws DuplicateMessageException if the input is a message that has already been received.
|
||||
* @throws LegacyMessageException if the input is a message formatted by a protocol version that
|
||||
* is no longer supported.
|
||||
* @throws NoSessionException if there is no established session for this contact.
|
||||
*/
|
||||
public byte[] decrypt(WhisperMessage ciphertext, DecryptionCallback callback)
|
||||
throws InvalidMessageException, DuplicateMessageException, LegacyMessageException,
|
||||
NoSessionException
|
||||
{
|
||||
@@ -194,6 +248,8 @@ public class SessionCipher {
|
||||
SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId);
|
||||
byte[] plaintext = decrypt(sessionRecord, ciphertext);
|
||||
|
||||
callback.handlePlaintext(plaintext);
|
||||
|
||||
sessionStore.storeSession(recipientId, deviceId, sessionRecord);
|
||||
|
||||
return plaintext;
|
||||
@@ -324,7 +380,7 @@ public class SessionCipher {
|
||||
}
|
||||
}
|
||||
|
||||
if (chainKey.getIndex() - counter > 2000) {
|
||||
if (counter - chainKey.getIndex() > 2000) {
|
||||
throw new InvalidMessageException("Over 2000 messages into the future!");
|
||||
}
|
||||
|
||||
@@ -401,4 +457,13 @@ public class SessionCipher {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static interface DecryptionCallback {
|
||||
public void handlePlaintext(byte[] plaintext);
|
||||
}
|
||||
|
||||
private static class NullDecryptionCallback implements DecryptionCallback {
|
||||
@Override
|
||||
public void handlePlaintext(byte[] plaintext) {}
|
||||
}
|
||||
}
|
||||
@@ -1,285 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009 ZXing authors
|
||||
*
|
||||
* 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 org.whispersystems.textsecure.zxing.integration;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Activity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
/**
|
||||
* <p>A utility class which helps ease integration with Barcode Scanner via {@link Intent}s. This is a simple
|
||||
* way to invoke barcode scanning and receive the result, without any need to integrate, modify, or learn the
|
||||
* project's source code.</p>
|
||||
*
|
||||
* <h2>Initiating a barcode scan</h2>
|
||||
*
|
||||
* <p>Integration is essentially as easy as calling {@link #initiateScan(Activity)} and waiting
|
||||
* for the result in your app.</p>
|
||||
*
|
||||
* <p>It does require that the Barcode Scanner application is installed. The
|
||||
* {@link #initiateScan(Activity)} method will prompt the user to download the application, if needed.</p>
|
||||
*
|
||||
* <p>There are a few steps to using this integration. First, your {@link Activity} must implement
|
||||
* the method {@link Activity#onActivityResult(int, int, Intent)} and include a line of code like this:</p>
|
||||
*
|
||||
* <p>{@code
|
||||
* public void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
* IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
|
||||
* if (scanResult != null) {
|
||||
* // handle scan result
|
||||
* }
|
||||
* // else continue with any other code you need in the method
|
||||
* ...
|
||||
* }
|
||||
* }</p>
|
||||
*
|
||||
* <p>This is where you will handle a scan result.
|
||||
* Second, just call this in response to a user action somewhere to begin the scan process:</p>
|
||||
*
|
||||
* <p>{@code IntentIntegrator.initiateScan(yourActivity);}</p>
|
||||
*
|
||||
* <p>You can use {@link #initiateScan(Activity, CharSequence, CharSequence, CharSequence, CharSequence)} or
|
||||
* {@link #initiateScan(Activity, int, int, int, int)} to customize the download prompt with
|
||||
* different text labels.</p>
|
||||
*
|
||||
* <p>Note that {@link #initiateScan(Activity)} returns an {@link AlertDialog} which is non-null if the
|
||||
* user was prompted to download the application. This lets the calling app potentially manage the dialog.
|
||||
* In particular, ideally, the app dismisses the dialog if it's still active in its {@link Activity#onPause()}
|
||||
* method.</p>
|
||||
*
|
||||
* <h2>Sharing text via barcode</h2>
|
||||
*
|
||||
* <p>To share text, encoded as a QR Code on-screen, similarly, see {@link #shareText(Activity, CharSequence)}.</p>
|
||||
*
|
||||
* <p>Some code, particularly download integration, was contributed from the Anobiit application.</p>
|
||||
*
|
||||
* @author Sean Owen
|
||||
* @author Fred Lin
|
||||
* @author Isaac Potoczny-Jones
|
||||
* @author Brad Drehmer
|
||||
*/
|
||||
public final class IntentIntegrator {
|
||||
|
||||
public static final int REQUEST_CODE = 0x0ba7c0de; // get it?
|
||||
|
||||
public static final String DEFAULT_TITLE = "Install Barcode Scanner?";
|
||||
public static final String DEFAULT_MESSAGE =
|
||||
"This application requires Barcode Scanner. Would you like to install it?";
|
||||
public static final String DEFAULT_YES = "Yes";
|
||||
public static final String DEFAULT_NO = "No";
|
||||
|
||||
// supported barcode formats
|
||||
public static final String PRODUCT_CODE_TYPES = "UPC_A,UPC_E,EAN_8,EAN_13";
|
||||
public static final String ONE_D_CODE_TYPES = PRODUCT_CODE_TYPES + ",CODE_39,CODE_93,CODE_128";
|
||||
public static final String QR_CODE_TYPES = "QR_CODE";
|
||||
public static final String ALL_CODE_TYPES = null;
|
||||
|
||||
private IntentIntegrator() {
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #initiateScan(Activity, CharSequence, CharSequence, CharSequence, CharSequence)} --
|
||||
* same, but uses default English labels.
|
||||
*/
|
||||
public static AlertDialog initiateScan(Activity activity) {
|
||||
return initiateScan(activity, DEFAULT_TITLE, DEFAULT_MESSAGE, DEFAULT_YES, DEFAULT_NO);
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #initiateScan(Activity, CharSequence, CharSequence, CharSequence, CharSequence)} --
|
||||
* same, but takes string IDs which refer
|
||||
* to the {@link Activity}'s resource bundle entries.
|
||||
*/
|
||||
public static AlertDialog initiateScan(Activity activity,
|
||||
int stringTitle,
|
||||
int stringMessage,
|
||||
int stringButtonYes,
|
||||
int stringButtonNo) {
|
||||
return initiateScan(activity,
|
||||
activity.getString(stringTitle),
|
||||
activity.getString(stringMessage),
|
||||
activity.getString(stringButtonYes),
|
||||
activity.getString(stringButtonNo));
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #initiateScan(Activity, CharSequence, CharSequence, CharSequence, CharSequence, CharSequence)} --
|
||||
* same, but scans for all supported barcode types.
|
||||
* @param stringTitle title of dialog prompting user to download Barcode Scanner
|
||||
* @param stringMessage text of dialog prompting user to download Barcode Scanner
|
||||
* @param stringButtonYes text of button user clicks when agreeing to download
|
||||
* Barcode Scanner (e.g. "Yes")
|
||||
* @param stringButtonNo text of button user clicks when declining to download
|
||||
* Barcode Scanner (e.g. "No")
|
||||
* @return an {@link AlertDialog} if the user was prompted to download the app,
|
||||
* null otherwise
|
||||
*/
|
||||
public static AlertDialog initiateScan(Activity activity,
|
||||
CharSequence stringTitle,
|
||||
CharSequence stringMessage,
|
||||
CharSequence stringButtonYes,
|
||||
CharSequence stringButtonNo) {
|
||||
|
||||
return initiateScan(activity,
|
||||
stringTitle,
|
||||
stringMessage,
|
||||
stringButtonYes,
|
||||
stringButtonNo,
|
||||
ALL_CODE_TYPES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes scanning.
|
||||
*
|
||||
* @param stringTitle title of dialog prompting user to download Barcode Scanner
|
||||
* @param stringMessage text of dialog prompting user to download Barcode Scanner
|
||||
* @param stringButtonYes text of button user clicks when agreeing to download
|
||||
* Barcode Scanner (e.g. "Yes")
|
||||
* @param stringButtonNo text of button user clicks when declining to download
|
||||
* Barcode Scanner (e.g. "No")
|
||||
* @param stringDesiredBarcodeFormats a comma separated list of codes you would
|
||||
* like to scan for.
|
||||
* @return an {@link AlertDialog} if the user was prompted to download the app,
|
||||
* null otherwise
|
||||
* @throws InterruptedException if timeout expires before a scan completes
|
||||
*/
|
||||
public static AlertDialog initiateScan(Activity activity,
|
||||
CharSequence stringTitle,
|
||||
CharSequence stringMessage,
|
||||
CharSequence stringButtonYes,
|
||||
CharSequence stringButtonNo,
|
||||
CharSequence stringDesiredBarcodeFormats) {
|
||||
Intent intentScan = new Intent("com.google.zxing.client.android.SCAN");
|
||||
intentScan.addCategory(Intent.CATEGORY_DEFAULT);
|
||||
|
||||
// check which types of codes to scan for
|
||||
if (stringDesiredBarcodeFormats != null) {
|
||||
// set the desired barcode types
|
||||
intentScan.putExtra("SCAN_FORMATS", stringDesiredBarcodeFormats);
|
||||
}
|
||||
|
||||
try {
|
||||
activity.startActivityForResult(intentScan, REQUEST_CODE);
|
||||
return null;
|
||||
} catch (ActivityNotFoundException e) {
|
||||
return showDownloadDialog(activity, stringTitle, stringMessage, stringButtonYes, stringButtonNo);
|
||||
}
|
||||
}
|
||||
|
||||
private static AlertDialog showDownloadDialog(final Activity activity,
|
||||
CharSequence stringTitle,
|
||||
CharSequence stringMessage,
|
||||
CharSequence stringButtonYes,
|
||||
CharSequence stringButtonNo) {
|
||||
AlertDialog.Builder downloadDialog = new AlertDialog.Builder(activity);
|
||||
downloadDialog.setTitle(stringTitle);
|
||||
downloadDialog.setMessage(stringMessage);
|
||||
downloadDialog.setPositiveButton(stringButtonYes, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
Uri uri = Uri.parse("market://search?q=pname:com.google.zxing.client.android");
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
});
|
||||
downloadDialog.setNegativeButton(stringButtonNo, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialogInterface, int i) {}
|
||||
});
|
||||
return downloadDialog.show();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Call this from your {@link Activity}'s
|
||||
* {@link Activity#onActivityResult(int, int, Intent)} method.</p>
|
||||
*
|
||||
* @return null if the event handled here was not related to {@link IntentIntegrator}, or
|
||||
* else an {@link IntentResult} containing the result of the scan. If the user cancelled scanning,
|
||||
* the fields will be null.
|
||||
*/
|
||||
public static IntentResult parseActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
if (requestCode == REQUEST_CODE) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
String contents = intent.getStringExtra("SCAN_RESULT");
|
||||
String formatName = intent.getStringExtra("SCAN_RESULT_FORMAT");
|
||||
return new IntentResult(contents, formatName);
|
||||
} else {
|
||||
return new IntentResult(null, null);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #shareText(Activity, CharSequence, CharSequence, CharSequence, CharSequence, CharSequence)} --
|
||||
* same, but uses default English labels.
|
||||
*/
|
||||
public static void shareText(Activity activity, CharSequence text) {
|
||||
shareText(activity, text, DEFAULT_TITLE, DEFAULT_MESSAGE, DEFAULT_YES, DEFAULT_NO);
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #shareText(Activity, CharSequence, CharSequence, CharSequence, CharSequence, CharSequence)} --
|
||||
* same, but takes string IDs which refer to the {@link Activity}'s resource bundle entries.
|
||||
*/
|
||||
public static void shareText(Activity activity,
|
||||
CharSequence text,
|
||||
int stringTitle,
|
||||
int stringMessage,
|
||||
int stringButtonYes,
|
||||
int stringButtonNo) {
|
||||
shareText(activity,
|
||||
text,
|
||||
activity.getString(stringTitle),
|
||||
activity.getString(stringMessage),
|
||||
activity.getString(stringButtonYes),
|
||||
activity.getString(stringButtonNo));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shares the given text by encoding it as a barcode, such that another user can
|
||||
* scan the text off the screen of the device.
|
||||
*
|
||||
* @param text the text string to encode as a barcode
|
||||
* @param stringTitle title of dialog prompting user to download Barcode Scanner
|
||||
* @param stringMessage text of dialog prompting user to download Barcode Scanner
|
||||
* @param stringButtonYes text of button user clicks when agreeing to download
|
||||
* Barcode Scanner (e.g. "Yes")
|
||||
* @param stringButtonNo text of button user clicks when declining to download
|
||||
* Barcode Scanner (e.g. "No")
|
||||
*/
|
||||
public static void shareText(Activity activity,
|
||||
CharSequence text,
|
||||
CharSequence stringTitle,
|
||||
CharSequence stringMessage,
|
||||
CharSequence stringButtonYes,
|
||||
CharSequence stringButtonNo) {
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setAction("com.google.zxing.client.android.ENCODE");
|
||||
intent.putExtra("ENCODE_TYPE", "TEXT_TYPE");
|
||||
intent.putExtra("ENCODE_DATA", text);
|
||||
try {
|
||||
activity.startActivity(intent);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
showDownloadDialog(activity, stringTitle, stringMessage, stringButtonYes, stringButtonNo);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009 ZXing authors
|
||||
*
|
||||
* 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 org.whispersystems.textsecure.zxing.integration;
|
||||
|
||||
/**
|
||||
* <p>Encapsulates the result of a barcode scan invoked through {@link IntentIntegrator}.</p>
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
public final class IntentResult {
|
||||
|
||||
private final String contents;
|
||||
private final String formatName;
|
||||
|
||||
IntentResult(String contents, String formatName) {
|
||||
this.contents = contents;
|
||||
this.formatName = formatName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return raw content of barcode
|
||||
*/
|
||||
public String getContents() {
|
||||
return contents;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return name of format, like "QR_CODE", "UPC_A". See <code>BarcodeFormat</code> for more format names.
|
||||
*/
|
||||
public String getFormatName() {
|
||||
return formatName;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -93,8 +93,13 @@ Trebat ćete ponovno registrirati vaš broj telefona kako biste koristili instan
|
||||
<string name="ConversationFragment_sender_s_transport_s_sent_s_received_s">Pošiljatelj: %1$s\nTransport: %2$s\nPoslano: %3$s\nPrimljeno: %4$s</string>
|
||||
<string name="ConversationFragment_confirm_message_delete">Potvrda brisanja poruke</string>
|
||||
<string name="ConversationFragment_are_you_sure_you_want_to_permanently_delete_this_message">Jeste li sigurni da želite trajno obrisati ovu poruku?</string>
|
||||
<string name="ConversationFragment_save_to_sd_card">Spremi na disk?</string>
|
||||
<string name="ConversationFragment_this_media_has_been_stored_in_an_encrypted_database_warning">Spremanje ovog medija na disk će omogućiti pristup mediju iz drugih aplikacija na vašem telefonu.\n\nNastavi?</string>
|
||||
<string name="ConversationFragment_error_while_saving_attachment_to_sd_card">Greška prilikom spremanja privitka na disk!</string>
|
||||
<string name="ConversationFragment_success_exclamation">Uspješno!</string>
|
||||
<string name="ConversationFragment_unable_to_write_to_sd_card_exclamation">Nije moguće pisati na disk!</string>
|
||||
<string name="ConversationFragment_saving_attachment">Spremanje privitka</string>
|
||||
<string name="ConversationFragment_saving_attachment_to_sd_card">Spremanje privitka na disk...</string>
|
||||
<!--ConversationListAdapter-->
|
||||
<string name="ConversationListAdapter_key_exchange_message">Poruka za razmjenu ključa...</string>
|
||||
<!--ConversationListFragment-->
|
||||
@@ -458,11 +463,14 @@ Uvezi nekriptiranu kopiju kompatibilnu s \'SMSBackup And Restore\'.</string>
|
||||
<!--receive_key_activity-->
|
||||
<string name="receive_key_activity__complete">Završeno</string>
|
||||
<!--registration_activity-->
|
||||
<string name="registration_activity__textsecure_can_use_instant_messages_to_avoid_sms_charges_when_communicating_with_other_textsecure_users">
|
||||
Registracija je besplatna i povećava privatnost prilikom slanja poruka drugim TextSecure korisnicima. Provjerite svoj broj telefona.</string>
|
||||
<string name="registration_activity__your_country">VAŠA ZEMLJA</string>
|
||||
<string name="registration_activity__your_country_code_and_phone_number">POZIVNI BROJ ZEMLJE I
|
||||
TELEFONSKI BROJ</string>
|
||||
<string name="registration_activity__phone_number">TELEFONSKI BROJ</string>
|
||||
<string name="registration_activity__register">Registriraj</string>
|
||||
<string name="registration_activity__registration_will_transmit_some_contact_information_to_the_server_temporariliy">Registracija šalje neke informacije o kontaktima na poslužitelj. Podaci se ne pohranjuju trajno.</string>
|
||||
<string name="registration_activity__skip">Preskoči</string>
|
||||
<!--registration_problems-->
|
||||
<string name="registration_problems__some_possible_problems_include">Neki mogući problemi
|
||||
@@ -542,6 +550,7 @@ neuspješno.</string>
|
||||
<string name="AndroidManifest__manage_identity_keys">Upravljajte ključevima identiteta</string>
|
||||
<string name="AndroidManifest__complete_key_exchange">Završite razmjenu ključeva</string>
|
||||
<string name="AndroidManifest__log_submit">Pošaljite debug zapise</string>
|
||||
<string name="AndroidManifest__media_preview">Prikaz medija</string>
|
||||
<!--arrays.xml-->
|
||||
<string name="arrays__import_export">Uvoz / izvoz</string>
|
||||
<string name="arrays__my_identity_key">Moj ključ identiteta</string>
|
||||
@@ -718,7 +727,10 @@ Povećajte privatnost i izbjegnite SMS troškove koristeći podatkovni kanal za
|
||||
<string name="reminder_header_push_title">Omogući TextSecure poruke?</string>
|
||||
<string name="reminder_header_push_text">Instant isporuka, pojačana privatnost i bez SMS troškova.</string>
|
||||
<!--MediaPreviewActivity-->
|
||||
<string name="MediaPreviewActivity_you">Vi</string>
|
||||
<!--media_preview-->
|
||||
<string name="media_preview__save_title">Spremi</string>
|
||||
<!--media_preview_activity-->
|
||||
<string name="media_preview_activity__image_content_description">Prikaz slike</string>
|
||||
<!--EOF-->
|
||||
</resources>
|
||||
|
||||
@@ -28,7 +28,7 @@ U zal uw telefoonnummer opnieuw moeten registreren als u push berichten weer wil
|
||||
<string name="ApplicationPreferencesActivity_updating_directory">Contactpersonen updaten</string>
|
||||
<string name="ApplicationPreferencesActivity_updating_push_directory">Pushcontactpersonen updaten...</string>
|
||||
<string name="ApplicationPreferencesActivity_sms_enabled">Inkomende SMS geactiveerd</string>
|
||||
<string name="ApplicationPreferencesActivity_touch_to_change_your_default_sms_app">Raak aan om uw standaard SMS applicatie te veranderen</string>
|
||||
<string name="ApplicationPreferencesActivity_touch_to_change_your_default_sms_app">Aanraken om uw standaard SMS applicatie te veranderen</string>
|
||||
<string name="ApplicationPreferencesActivity_sms_disabled">Inkomende SMS uitgeschakeld</string>
|
||||
<string name="ApplicationPreferencesActivity_touch_to_make_textsecure_your_default_sms_app">Raak aan om TextSecure uw standaard SMS applicatie te maken</string>
|
||||
<!--AttchmentManager-->
|
||||
@@ -516,7 +516,7 @@ TextSecure heeft te lang moeten wachten op het binnenkomen van de verificatie-SM
|
||||
<string name="AndroidManifest__select_contact">Selecteer contact</string>
|
||||
<string name="AndroidManifest__textsecure_detected">TextSecure gedetecteerd</string>
|
||||
<string name="AndroidManifest__public_identity_key">Publieke identiteitssleutel</string>
|
||||
<string name="AndroidManifest__change_passphrase">Verander wachtwoord</string>
|
||||
<string name="AndroidManifest__change_passphrase">Wachtwoord veranderen</string>
|
||||
<string name="AndroidManifest__verify_session">Sessie verifiëren</string>
|
||||
<string name="AndroidManifest__verify_identity">Identiteit verifiëren</string>
|
||||
<string name="AndroidManifest__manage_identity_keys">Beheer identiteitssleutels</string>
|
||||
@@ -541,9 +541,9 @@ TextSecure heeft te lang moeten wachten op het binnenkomen van de verificatie-SM
|
||||
<string name="preferences__display_settings">Beeldscherminstellingen</string>
|
||||
<string name="preferences__choose_identity">Identiteit kiezen</string>
|
||||
<string name="preferences__choose_your_contact_entry_from_the_contacts_list">Kies uw contactinformatie uit de contactpersonenlijst.</string>
|
||||
<string name="preferences__change_passphrase">Verander wachtwoord</string>
|
||||
<string name="preferences__change_passphrase">Wachtwoord veranderen</string>
|
||||
<string name="preferences__change_my_passphrase">Mijn wachtwoord veranderen</string>
|
||||
<string name="preferences__complete_key_exchanges">Voltooi sleuteluitwisselingen</string>
|
||||
<string name="preferences__complete_key_exchanges">Sleuteluitwisselingen voltooien</string>
|
||||
<string name="preferences__disable_passphrase">Wachtwoord uitschakelen</string>
|
||||
<string name="preferences__disable_local_encryption_of_messages_and_keys">Lokale versleuteling van berichten en sleutels uitschakelen</string>
|
||||
<string name="preferences__screen_security">Schermbeveiliging</string>
|
||||
@@ -595,12 +595,12 @@ TextSecure heeft te lang moeten wachten op het binnenkomen van de verificatie-SM
|
||||
<string name="preferences__mms_proxy_host_optional">MMS Proxy Host (Optioneel)</string>
|
||||
<string name="preferences__mms_proxy_port_optional">MMS Proxy Poort (Optioneel)</string>
|
||||
<string name="preferences__sms_delivery_reports">SMS ontvangstbevestigingen</string>
|
||||
<string name="preferences__request_a_delivery_report_for_each_sms_message_you_send">Verzoek om een ontvangstbevestiging voor ieder verzonden SMS bericht</string>
|
||||
<string name="preferences__request_a_delivery_report_for_each_sms_message_you_send">Verzoeken om een ontvangstbevestiging voor ieder verzonden SMS bericht</string>
|
||||
<string name="preferences__automatically_delete_older_messages_once_a_conversation_thread_exceeds_a_specified_length">Automatisch oudere berichten verwijderen wanneer een gesprek meer dan een bepaald aantal berichten bevat</string>
|
||||
<string name="preferences__delete_old_messages">Verwijder oude berichten</string>
|
||||
<string name="preferences__storage">Opslag</string>
|
||||
<string name="preferences__conversation_length_limit">Gesprekslengte limiet</string>
|
||||
<string name="preferences__trim_all_threads_now">Oudere gespreksberichten nu verwijderen</string>
|
||||
<string name="preferences__trim_all_threads_now">Oude berichten nu verwijderen</string>
|
||||
<string name="preferences__scan_through_all_conversation_threads_and_enforce_conversation_length_limits">Alle gesprekken scannen en de maximale gesprekslengte toepassen</string>
|
||||
<string name="preferences__light_theme">Licht thema</string>
|
||||
<string name="preferences__dark_theme">Donker thema</string>
|
||||
@@ -611,7 +611,8 @@ TextSecure heeft te lang moeten wachten op het binnenkomen van de verificatie-SM
|
||||
<string name="preferences__make_default_sms_app">Stel in als standaard SMS-app</string>
|
||||
<string name="preferences__make_textsecure_the_default_sms_mms_app">Stel TextSecure in als standaard SMS/MMS-applicatie voor uw systeem.</string>
|
||||
<string name="preferences__use_data_channel">Pushberichten</string>
|
||||
<string name="preferences__use_the_data_channel_for_communication_with_other_textsecure_users">Privacy verbeteren en SMS-kosten vermijden door het datakanaal te gebruiken om te communiceren met andere TextSecure gebruikers</string>
|
||||
<string name="preferences__use_the_data_channel_for_communication_with_other_textsecure_users">
|
||||
Privacy verbeteren en SMS-kosten vermijden door het datakanaal te gebruiken voor communicatie met andere TextSecure gebruikers</string>
|
||||
<string name="preferences__allow_sms_fallback">SMS versturen naar</string>
|
||||
<string name="preferences__allow_sms_fallback_disabled_reason">TextSecure is momenteel uw standaard SMS applicatie. Selecteer alstublieft een andere SMS applicatie om deze voorkeur te veranderen.</string>
|
||||
<string name="preferences__refresh_push_directory">Pushcontacten verversen</string>
|
||||
|
||||
@@ -31,6 +31,7 @@ Za ponovno uporabo potisnih sporočil se boste morali zopet prijaviti s svojo te
|
||||
<string name="ApplicationPreferencesActivity_sms_disabled">Dohodna SMS sporočila izklopljena</string>
|
||||
<string name="ApplicationPreferencesActivity_touch_to_make_textsecure_your_default_sms_app">Z dotikom nastavi TexteScure za privzeto aplikacijo SMS</string>
|
||||
<!--AttchmentManager-->
|
||||
<string name="AttachmentManager_cant_open_media_selection">Ne najdem aplikacije za izbor datotek.</string>
|
||||
<!--AttachmentTypeSelectorAdapter-->
|
||||
<string name="AttachmentTypeSelectorAdapter_picture">Slika</string>
|
||||
<string name="AttachmentTypeSelectorAdapter_video">Video</string>
|
||||
@@ -56,6 +57,7 @@ Za ponovno uporabo potisnih sporočil se boste morali zopet prijaviti s svojo te
|
||||
<string name="ConversationItem_click_to_approve_unencrypted_sms_dialog_title">Preklopim na nešifriran SMS?</string>
|
||||
<string name="ConversationItem_click_to_approve_unencrypted_mms_dialog_title">Preklopim na nešifriran MMS?</string>
|
||||
<string name="ConversationItem_click_to_approve_unencrypted_dialog_message">To sporočilo <b>ne bo</b> šifrirano, ker varna seja ne more biti vzpostavljena.\n\nPošljem nešifrirano sporočilo?</string>
|
||||
<string name="ConversationItem_unable_to_open_media">Ne najdem aplikacije za odpiranje te vrste datotek.</string>
|
||||
<!--ConversationActivity-->
|
||||
<string name="ConversationActivity_initiate_secure_session_question">Začnem varno sejo?</string>
|
||||
<string name="ConversationActivity_initiate_secure_session_with_s_question">Začnem varno sejo z %s?</string>
|
||||
@@ -88,8 +90,13 @@ Za ponovno uporabo potisnih sporočil se boste morali zopet prijaviti s svojo te
|
||||
<string name="ConversationFragment_sender_s_transport_s_sent_s_received_s">Pošiljatelj: %1$s\nNačin prenosa: %2$s\nPoslano: %3$s\nPrejeto: %4$s</string>
|
||||
<string name="ConversationFragment_confirm_message_delete">Potrdite izbris sporočila</string>
|
||||
<string name="ConversationFragment_are_you_sure_you_want_to_permanently_delete_this_message">Ste prepričani, da želite dokonćno izbrisati sporočilo?</string>
|
||||
<string name="ConversationFragment_save_to_sd_card">Spravim v sistemsko shrambo?</string>
|
||||
<string name="ConversationFragment_this_media_has_been_stored_in_an_encrypted_database_warning">S shranitvijo datoteke v sistemsko shrambo bo ta dostopna tudi drugim aplikacijam.\n\nNadaljujem?</string>
|
||||
<string name="ConversationFragment_error_while_saving_attachment_to_sd_card">Napaka pri shranjevanju priponke v sistemsko shrambo!</string>
|
||||
<string name="ConversationFragment_success_exclamation">Uspešno opravljeno!</string>
|
||||
<string name="ConversationFragment_unable_to_write_to_sd_card_exclamation">Ne morem shranjevati v sistemsko shrambo!</string>
|
||||
<string name="ConversationFragment_saving_attachment">Shranjujem priponko</string>
|
||||
<string name="ConversationFragment_saving_attachment_to_sd_card">Shranjujem v sistemsko shrambo...</string>
|
||||
<!--ConversationListAdapter-->
|
||||
<string name="ConversationListAdapter_key_exchange_message">Sporočilo za izmenjavo ključev...</string>
|
||||
<!--ConversationListFragment-->
|
||||
@@ -302,7 +309,7 @@ Prejeto sporočilo z neznanim identifikacijskim ključem. Kliknite za obdelavo i
|
||||
<string name="MessageNotifier_message_delivery_failed">Dostava sporočila ni uspela.</string>
|
||||
<string name="MessageNotifier_failed_to_deliver_message">Neuspešna dostava sporočila.</string>
|
||||
<string name="MessageNotifier_error_delivering_message">Napaka pri dostavi sporočila.</string>
|
||||
<string name="MessageNotifier_mark_all_as_read">Označi vsa kot prebrana</string>
|
||||
<string name="MessageNotifier_mark_all_as_read">Označi vse kot prebrano</string>
|
||||
<string name="MessageNotifier_mark_as_read">Označi kot prebrano</string>
|
||||
<!--ViewLocalIdentityActivity-->
|
||||
<string name="ViewLocalIdentityActivity_regenerating">Ustvarjam nov ključ...</string>
|
||||
@@ -423,11 +430,14 @@ Prejeto sporočilo z neznanim identifikacijskim ključem. Kliknite za obdelavo i
|
||||
<!--receive_key_activity-->
|
||||
<string name="receive_key_activity__complete">Dokončaj</string>
|
||||
<!--registration_activity-->
|
||||
<string name="registration_activity__textsecure_can_use_instant_messages_to_avoid_sms_charges_when_communicating_with_other_textsecure_users">
|
||||
Registracija je brezplačna in izboljša zasebnost pri pošiljanju sporočil drugim uporabnikom TextSecure. Prosim preverite svojo telefonsko številko.</string>
|
||||
<string name="registration_activity__your_country">VAŠA DRŽAVA</string>
|
||||
<string name="registration_activity__your_country_code_and_phone_number">KODA DRŽAVE IN VAŠA
|
||||
TELEFONSKA ŠTEVILKA</string>
|
||||
<string name="registration_activity__phone_number">TELEFONSKA ŠTEVILKA</string>
|
||||
<string name="registration_activity__register">Registriraj</string>
|
||||
<string name="registration_activity__registration_will_transmit_some_contact_information_to_the_server_temporariliy">Pri registraciji se nekateri podatki uporabnika začasno posredujejo na strežnik.</string>
|
||||
<string name="registration_activity__skip">Preskoči</string>
|
||||
<!--registration_problems-->
|
||||
<string name="registration_problems__some_possible_problems_include">Nekatere možni razlogi
|
||||
@@ -505,9 +515,10 @@ bila uspešna.</string>
|
||||
<string name="AndroidManifest__manage_identity_keys">Upravljanje identifikacijskih ključev</string>
|
||||
<string name="AndroidManifest__complete_key_exchange">Dokončaj izmenjavo ključev</string>
|
||||
<string name="AndroidManifest__log_submit">Oddaj sistemsko zabeležbo</string>
|
||||
<string name="AndroidManifest__media_preview">Ogled medija</string>
|
||||
<!--arrays.xml-->
|
||||
<string name="arrays__import_export">Uvoz / izvoz</string>
|
||||
<string name="arrays__my_identity_key">Moj identifikacijski ključ</string>
|
||||
<string name="arrays__import_export">Uvoz/izvoz</string>
|
||||
<string name="arrays__my_identity_key">Moja identifikacija</string>
|
||||
<!--preferences.xml-->
|
||||
<string name="preferences__general">Splošno</string>
|
||||
<string name="preferences__push_sms_category">Pošiljanje in prejemanje</string>
|
||||
@@ -680,7 +691,10 @@ bila uspešna.</string>
|
||||
<string name="reminder_header_push_title">Vklopim sporočila TextSecure?</string>
|
||||
<string name="reminder_header_push_text">Takojšnja dostava, večja zasebnost, brez stroškov SMS.</string>
|
||||
<!--MediaPreviewActivity-->
|
||||
<string name="MediaPreviewActivity_you">Vi</string>
|
||||
<!--media_preview-->
|
||||
<string name="media_preview__save_title">Shrani</string>
|
||||
<!--media_preview_activity-->
|
||||
<string name="media_preview_activity__image_content_description">Ogled slike</string>
|
||||
<!--EOF-->
|
||||
</resources>
|
||||
|
||||
@@ -149,6 +149,10 @@
|
||||
settings, and messages...
|
||||
</string>
|
||||
|
||||
<!-- GcmRefreshJob -->
|
||||
<string name="GcmRefreshJob_Permanent_TextSecure_communication_failure">Permanent TextSecure communication failure!</string>
|
||||
<string name="GcmRefreshJob_TextSecure_was_unable_to_register_with_Google_Play_Services">TextSecure was unable to register with Google Play Services. Communication over the data channel has been disabled, please try re-registering from the TextSecure settings menu.</string>
|
||||
|
||||
<!-- GroupCreateActivity -->
|
||||
<string name="GroupCreateActivity_actionbar_title">New group</string>
|
||||
<string name="GroupCreateActivity_actionbar_update_title">Update group</string>
|
||||
|
||||
@@ -16,16 +16,26 @@
|
||||
<!-- ActionBar styles -->
|
||||
<style name="TextSecure.DarkActionBar"
|
||||
parent="@style/Widget.AppCompat.ActionBar">
|
||||
<item name="android:icon">@drawable/actionbar_icon_holo_dark</item>
|
||||
<item name="icon">@drawable/actionbar_icon_holo_dark</item>
|
||||
<item name="background">@color/gray95</item>
|
||||
<item name="elevation">2dp</item>
|
||||
<item name="android:background">@color/gray95</item>
|
||||
<item name="android:logo">@drawable/actionbar_icon_holo_dark</item>
|
||||
<item name="logo">@drawable/actionbar_icon_holo_dark</item>
|
||||
</style>
|
||||
|
||||
<style name="TextSecure.LightActionBar"
|
||||
parent="@style/Widget.AppCompat.ActionBar">
|
||||
<item name="android:icon">@drawable/actionbar_icon_holo_light</item>
|
||||
<item name="icon">@drawable/actionbar_icon_holo_light</item>
|
||||
<item name="android:background">@color/gray5</item>
|
||||
<item name="background">@color/gray5</item>
|
||||
<item name="elevation">2dp</item>
|
||||
<item name="android:logo">@drawable/actionbar_icon_holo_light</item>
|
||||
<item name="logo">@drawable/actionbar_icon_holo_light</item>
|
||||
<item name="android:titleTextStyle">@style/TextSecure.TitleTextStyle</item>
|
||||
<item name="titleTextStyle">@style/TextSecure.TitleTextStyle</item>
|
||||
<item name="android:subtitleTextStyle">@style/TextSecure.SubtitleTextStyle</item>
|
||||
<item name="subtitleTextStyle">@style/TextSecure.SubtitleTextStyle</item>
|
||||
</style>
|
||||
|
||||
<style name="TextSecure.ClearTitleTextStyle" parent="TextAppearance.AppCompat.Widget.ActionBar.Title">
|
||||
@@ -43,7 +53,8 @@
|
||||
|
||||
<style name="TextSecure.IntroActionBar" parent="Widget.AppCompat.Light.ActionBar.Solid">
|
||||
<item name="background">@drawable/background_pattern_repeat</item>
|
||||
<item name="elevation">0dp</item>
|
||||
<item name="titleTextStyle">@style/TextSecure.ClearTitleTextStyle</item>
|
||||
<item name="icon">@android:color/transparent</item>
|
||||
</style>
|
||||
|
||||
<style name="transparent_progress">
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<style name="TextSecure.IntroTheme" parent="@style/Theme.AppCompat.Light">
|
||||
<item name="colorPrimary">@android:color/transparent</item>
|
||||
<!--<item name="colorPrimary">@android:color/transparent</item>-->
|
||||
<item name="actionBarStyle">@style/TextSecure.IntroActionBar</item>
|
||||
<item name="android:windowContentOverlay">@null</item>
|
||||
</style>
|
||||
|
||||
<style name="TextSecure.LightTheme" parent="@style/Theme.AppCompat.Light">
|
||||
<item name="logo">@drawable/actionbar_icon_holo_light</item>
|
||||
<item name="android:logo">@drawable/actionbar_icon_holo_light</item>
|
||||
<item name="android:actionBarStyle">@style/TextSecure.LightActionBar</item>
|
||||
<item name="actionBarStyle">@style/TextSecure.LightActionBar</item>
|
||||
<item name="colorPrimary">@color/gray5</item>
|
||||
<item name="colorPrimaryDark">@color/gray95</item>
|
||||
<item name="colorAccent">#ff259b24</item>
|
||||
<item name="android:windowContentOverlay">@drawable/compat_actionbar_shadow_background</item>
|
||||
<item name="conversation_list_item_background_read">@drawable/conversation_list_item_background_read_light</item>
|
||||
<item name="conversation_list_item_background_unread">@drawable/conversation_list_item_background_unread_light</item>
|
||||
<item name="conversation_list_item_background_selected">@drawable/list_selected_holo_light</item>
|
||||
@@ -84,10 +83,11 @@
|
||||
</style>
|
||||
|
||||
<style name="TextSecure.DarkTheme" parent="@style/Theme.AppCompat">
|
||||
<item name="logo">@drawable/actionbar_icon_holo_dark</item>
|
||||
<item name="android:logo">@drawable/actionbar_icon_holo_dark</item>
|
||||
|
||||
<item name="android:actionBarStyle">@style/TextSecure.DarkActionBar</item>
|
||||
<item name="actionBarStyle">@style/TextSecure.DarkActionBar</item>
|
||||
<item name="colorPrimary">@color/gray95</item>
|
||||
<item name="colorPrimaryDark">@color/gray95</item>
|
||||
<item name="colorAccent">#ff259b24</item>
|
||||
<item name="conversation_list_item_background_read">@drawable/conversation_list_item_background_read_dark</item>
|
||||
<item name="conversation_list_item_background_unread">@drawable/conversation_list_item_background_unread_dark</item>
|
||||
<item name="conversation_list_item_background_selected">@drawable/list_selected_holo_dark</item>
|
||||
@@ -160,7 +160,7 @@
|
||||
</style>
|
||||
|
||||
<style name="TextSecure.Light.Dialog"
|
||||
parent="Theme.AppCompat.Light.Dialog"
|
||||
parent="Theme.AppCompat.Light.DialogWhenLarge"
|
||||
tools:ignore="NewApi">
|
||||
<item name="android:windowFrame">@null</item>
|
||||
<item name="android:windowTitleStyle">@style/TextSecureDialogWindowTitle</item>
|
||||
|
||||
@@ -118,6 +118,14 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
|
||||
dynamicLanguage.onResume(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
{
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
Fragment fragment = getSupportFragmentManager().findFragmentById(android.R.id.content);
|
||||
fragment.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
MemoryCleaner.clean((MasterSecret) getIntent().getParcelableExtra("master_secret"));
|
||||
|
||||
@@ -1037,6 +1037,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
ConversationFragment fragment = (ConversationFragment) getSupportFragmentManager()
|
||||
.findFragmentById(R.id.fragment_content);
|
||||
|
||||
if (fragment == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (refreshFragment) {
|
||||
fragment.reload(recipients, threadId);
|
||||
|
||||
|
||||
@@ -69,10 +69,6 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
|
||||
setContentView(R.layout.conversation_list_activity);
|
||||
|
||||
getSupportActionBar().setHomeButtonEnabled(true);
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
getSupportActionBar().setDisplayUseLogoEnabled(true);
|
||||
|
||||
getSupportActionBar().setTitle(R.string.app_name);
|
||||
|
||||
initializeResources();
|
||||
|
||||
@@ -23,13 +23,13 @@ import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.zxing.integration.android.IntentIntegrator;
|
||||
import com.google.zxing.integration.android.IntentResult;
|
||||
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
import org.whispersystems.libaxolotl.IdentityKey;
|
||||
import org.thoughtcrime.securesms.util.Dialogs;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
|
||||
import org.whispersystems.textsecure.zxing.integration.IntentIntegrator;
|
||||
import org.whispersystems.textsecure.zxing.integration.IntentResult;
|
||||
import org.whispersystems.libaxolotl.IdentityKey;
|
||||
|
||||
/**
|
||||
* Activity for initiating/receiving key QR code scans.
|
||||
@@ -99,11 +99,13 @@ public abstract class KeyScanningActivity extends PassphraseRequiredActionBarAct
|
||||
}
|
||||
|
||||
protected void initiateScan() {
|
||||
IntentIntegrator.initiateScan(this);
|
||||
IntentIntegrator intentIntegrator = new IntentIntegrator(this);
|
||||
intentIntegrator.initiateScan();
|
||||
}
|
||||
|
||||
protected void initiateDisplay() {
|
||||
IntentIntegrator.shareText(this, Base64.encodeBytes(getIdentityKeyToDisplay().serialize()));
|
||||
IntentIntegrator intentIntegrator = new IntentIntegrator(this);
|
||||
intentIntegrator.shareText(Base64.encodeBytes(getIdentityKeyToDisplay().serialize()));
|
||||
}
|
||||
|
||||
protected abstract String getScanString();
|
||||
|
||||
@@ -70,14 +70,17 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle bundle) {
|
||||
this.setTheme(R.style.TextSecure_DarkTheme);
|
||||
dynamicLanguage.onCreate(this);
|
||||
|
||||
super.onCreate(bundle);
|
||||
setFullscreenIfPossible();
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
dynamicLanguage.onCreate(this);
|
||||
this.setTheme(R.style.TextSecure_DarkTheme);
|
||||
super.onCreate(bundle);
|
||||
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
setContentView(R.layout.media_preview_activity);
|
||||
|
||||
initializeResources();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (C) 2014 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
public class PlayServicesProblemActivity extends FragmentActivity {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
PlayServicesProblemFragment fragment = new PlayServicesProblemFragment();
|
||||
fragment.show(getSupportFragmentManager(), "dialog");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (C) 2014 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
|
||||
import com.google.android.gms.common.GooglePlayServicesUtil;
|
||||
|
||||
public class PlayServicesProblemFragment extends DialogFragment {
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(@NonNull Bundle bundle) {
|
||||
int code = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity());
|
||||
return GooglePlayServicesUtil.getErrorDialog(code, getActivity(), 9111);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import android.util.Pair;
|
||||
|
||||
import com.google.i18n.phonenumbers.PhoneNumberUtil;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.crypto.MasterCipher;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
@@ -36,6 +37,7 @@ import org.thoughtcrime.securesms.database.model.DisplayRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.NotificationMmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.jobs.TrimThreadJob;
|
||||
import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||
@@ -52,6 +54,7 @@ import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Trimmer;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.jobqueue.JobManager;
|
||||
import org.whispersystems.libaxolotl.InvalidMessageException;
|
||||
import org.whispersystems.libaxolotl.util.guava.Optional;
|
||||
import org.whispersystems.textsecure.api.util.InvalidNumberException;
|
||||
@@ -154,8 +157,11 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
|
||||
private static final Map<Long, SoftReference<SlideDeck>> slideCache =
|
||||
Collections.synchronizedMap(new LRUCache<Long, SoftReference<SlideDeck>>(20));
|
||||
|
||||
private final JobManager jobManager;
|
||||
|
||||
public MmsDatabase(Context context, SQLiteOpenHelper databaseHelper) {
|
||||
super(context, databaseHelper);
|
||||
this.jobManager = ApplicationContext.getInstance(context).getJobManager();
|
||||
}
|
||||
|
||||
public int getMessageCountForThread(long threadId) {
|
||||
@@ -566,9 +572,9 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
|
||||
|
||||
DatabaseFactory.getThreadDatabase(context).update(threadId);
|
||||
notifyConversationListeners(threadId);
|
||||
Trimmer.trimThread(context, threadId);
|
||||
jobManager.add(new TrimThreadJob(context, threadId));
|
||||
|
||||
return new Pair<Long, Long>(messageId, threadId);
|
||||
return new Pair<>(messageId, threadId);
|
||||
}
|
||||
|
||||
public Pair<Long, Long> insertMessageInbox(MasterSecret masterSecret,
|
||||
@@ -644,7 +650,7 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
|
||||
DatabaseFactory.getThreadDatabase(context).setUnread(threadId);
|
||||
}
|
||||
|
||||
Trimmer.trimThread(context, threadId);
|
||||
jobManager.add(new TrimThreadJob(context, threadId));
|
||||
}
|
||||
|
||||
public long insertMessageOutbox(MasterSecret masterSecret, OutgoingMediaMessage message,
|
||||
@@ -690,7 +696,7 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
|
||||
|
||||
long messageId = insertMediaMessage(masterSecret, sendRequest.getPduHeaders(),
|
||||
sendRequest.getBody(), contentValues);
|
||||
Trimmer.trimThread(context, threadId);
|
||||
jobManager.add(new TrimThreadJob(context, threadId));
|
||||
|
||||
return messageId;
|
||||
}
|
||||
|
||||
@@ -27,8 +27,10 @@ import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.database.model.DisplayRecord;
|
||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.jobs.TrimThreadJob;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
|
||||
@@ -37,7 +39,7 @@ import org.thoughtcrime.securesms.sms.IncomingGroupMessage;
|
||||
import org.thoughtcrime.securesms.sms.IncomingKeyExchangeMessage;
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
||||
import org.thoughtcrime.securesms.util.Trimmer;
|
||||
import org.whispersystems.jobqueue.JobManager;
|
||||
import org.whispersystems.textsecure.api.util.InvalidNumberException;
|
||||
|
||||
import java.util.Set;
|
||||
@@ -86,8 +88,11 @@ public class SmsDatabase extends Database implements MmsSmsColumns {
|
||||
REPLY_PATH_PRESENT, SUBJECT, BODY, SERVICE_CENTER, RECEIPT_COUNT
|
||||
};
|
||||
|
||||
private final JobManager jobManager;
|
||||
|
||||
public SmsDatabase(Context context, SQLiteOpenHelper databaseHelper) {
|
||||
super(context, databaseHelper);
|
||||
this.jobManager = ApplicationContext.getInstance(context).getJobManager();
|
||||
}
|
||||
|
||||
private void updateTypeBitmask(long id, long maskOff, long maskOn) {
|
||||
@@ -329,7 +334,8 @@ public class SmsDatabase extends Database implements MmsSmsColumns {
|
||||
|
||||
DatabaseFactory.getThreadDatabase(context).update(record.getThreadId());
|
||||
notifyConversationListeners(record.getThreadId());
|
||||
Trimmer.trimThread(context, record.getThreadId());
|
||||
|
||||
jobManager.add(new TrimThreadJob(context, record.getThreadId()));
|
||||
reader.close();
|
||||
|
||||
return new Pair<>(newMessageId, record.getThreadId());
|
||||
@@ -417,9 +423,9 @@ public class SmsDatabase extends Database implements MmsSmsColumns {
|
||||
|
||||
DatabaseFactory.getThreadDatabase(context).update(threadId);
|
||||
notifyConversationListeners(threadId);
|
||||
Trimmer.trimThread(context, threadId);
|
||||
jobManager.add(new TrimThreadJob(context, threadId));
|
||||
|
||||
return new Pair<Long, Long>(messageId, threadId);
|
||||
return new Pair<>(messageId, threadId);
|
||||
}
|
||||
|
||||
public Pair<Long, Long> insertMessageInbox(IncomingTextMessage message) {
|
||||
@@ -450,7 +456,7 @@ public class SmsDatabase extends Database implements MmsSmsColumns {
|
||||
|
||||
DatabaseFactory.getThreadDatabase(context).update(threadId);
|
||||
notifyConversationListeners(threadId);
|
||||
Trimmer.trimThread(context, threadId);
|
||||
jobManager.add(new TrimThreadJob(context, threadId));
|
||||
|
||||
return messageId;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,35 @@
|
||||
/**
|
||||
* Copyright (C) 2014 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.GooglePlayServicesUtil;
|
||||
import com.google.android.gms.gcm.GoogleCloudMessaging;
|
||||
|
||||
import org.thoughtcrime.securesms.PlayServicesProblemActivity;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.push.TextSecureCommunicationFactory;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.jobqueue.JobParameters;
|
||||
@@ -31,22 +53,20 @@ public class GcmRefreshJob extends ContextJob {
|
||||
|
||||
@Override
|
||||
public void onRun() throws Exception {
|
||||
String registrationId = TextSecurePreferences.getGcmRegistrationId(context);
|
||||
TextSecureAccountManager accountManager = TextSecureCommunicationFactory.createManager(context);
|
||||
String registrationId = TextSecurePreferences.getGcmRegistrationId(context);
|
||||
|
||||
if (registrationId == null) {
|
||||
Log.w(TAG, "GCM registrationId expired, reregistering...");
|
||||
int result = GooglePlayServicesUtil.isGooglePlayServicesAvailable(context);
|
||||
|
||||
if (result != ConnectionResult.SUCCESS) {
|
||||
Toast.makeText(context, "Unable to register with GCM!", Toast.LENGTH_LONG).show();
|
||||
notifyGcmFailure();
|
||||
} else {
|
||||
String gcmId = GoogleCloudMessaging.getInstance(context).register(REGISTRATION_ID);
|
||||
accountManager.setGcmId(Optional.of(gcmId));
|
||||
TextSecurePreferences.setGcmRegistrationId(context, gcmId);
|
||||
}
|
||||
|
||||
String gcmId = GoogleCloudMessaging.getInstance(context).register(REGISTRATION_ID);
|
||||
TextSecureAccountManager accountManager = TextSecureCommunicationFactory.createManager(context);
|
||||
|
||||
accountManager.setGcmId(Optional.of(gcmId));
|
||||
|
||||
TextSecurePreferences.setGcmRegistrationId(context, gcmId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,4 +81,22 @@ public class GcmRefreshJob extends ContextJob {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void notifyGcmFailure() {
|
||||
Intent intent = new Intent(context, PlayServicesProblemActivity.class);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(context, 1122, intent, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
|
||||
|
||||
builder.setSmallIcon(R.drawable.icon_notification);
|
||||
builder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(),
|
||||
R.drawable.ic_action_warning_red));
|
||||
builder.setContentTitle(context.getString(R.string.GcmRefreshJob_Permanent_TextSecure_communication_failure));
|
||||
builder.setContentText(context.getString(R.string.GcmRefreshJob_TextSecure_was_unable_to_register_with_Google_Play_Services));
|
||||
builder.setTicker(context.getString(R.string.GcmRefreshJob_Permanent_TextSecure_communication_failure));
|
||||
builder.setVibrate(new long[] {0, 1000});
|
||||
builder.setContentIntent(pendingIntent);
|
||||
|
||||
((NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE))
|
||||
.notify(12, builder.build());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
65
src/org/thoughtcrime/securesms/jobs/TrimThreadJob.java
Normal file
65
src/org/thoughtcrime/securesms/jobs/TrimThreadJob.java
Normal file
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Copyright (C) 2014 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.jobqueue.Job;
|
||||
import org.whispersystems.jobqueue.JobParameters;
|
||||
|
||||
public class TrimThreadJob extends Job {
|
||||
|
||||
private static final String TAG = TrimThreadJob.class.getSimpleName();
|
||||
|
||||
private final Context context;
|
||||
private final long threadId;
|
||||
|
||||
public TrimThreadJob(Context context, long threadId) {
|
||||
super(JobParameters.newBuilder().withGroupId(TrimThreadJob.class.getSimpleName()).create());
|
||||
this.context = context;
|
||||
this.threadId = threadId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun() {
|
||||
boolean trimmingEnabled = TextSecurePreferences.isThreadLengthTrimmingEnabled(context);
|
||||
int threadLengthLimit = TextSecurePreferences.getThreadTrimLength(context);
|
||||
|
||||
if (!trimmingEnabled)
|
||||
return;
|
||||
|
||||
DatabaseFactory.getThreadDatabase(context).trimThread(threadId, threadLengthLimit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onShouldRetry(Exception exception) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCanceled() {
|
||||
Log.w(TAG, "Canceling trim attempt: " + threadId);
|
||||
}
|
||||
}
|
||||
@@ -14,22 +14,6 @@ public class Trimmer {
|
||||
new TrimmingProgressTask(context).execute(threadLengthLimit);
|
||||
}
|
||||
|
||||
public static void trimThread(final Context context, final long threadId) {
|
||||
boolean trimmingEnabled = TextSecurePreferences.isThreadLengthTrimmingEnabled(context);
|
||||
final int threadLengthLimit = TextSecurePreferences.getThreadTrimLength(context);
|
||||
|
||||
if (!trimmingEnabled)
|
||||
return;
|
||||
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
DatabaseFactory.getThreadDatabase(context).trimThread(threadId, threadLengthLimit);
|
||||
return null;
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
private static class TrimmingProgressTask extends AsyncTask<Integer, Integer, Void> implements ThreadDatabase.ProgressListener {
|
||||
private ProgressDialog progressDialog;
|
||||
private Context context;
|
||||
|
||||
Reference in New Issue
Block a user