Search in sources :

Example 41 with NonNull

use of androidx.annotation.NonNull in project kdeconnect-android by KDE.

the class SMSHelper method getMessages.

/**
 * Gets messages which match the selection
 *
 * @param uri Uri indicating the messages database to read
 * @param context android.content.Context running the request.
 * @param fetchColumns List of columns to fetch
 * @param selection Parameterizable filter to use with the ContentResolver query. May be null.
 * @param selectionArgs Parameters for selection. May be null.
 * @param sortOrder Sort ordering passed to Android's content resolver. May be null for unspecified
 * @param numberToGet Number of things to get from the result. Pass null to get all
 * @return Returns List<Message> of all messages in the return set, either in the order of sortOrder or in an unspecified order
 */
@NonNull
private static List<Message> getMessages(@NonNull Uri uri, @NonNull Context context, @NonNull Collection<String> fetchColumns, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder, @Nullable Long numberToGet) {
    List<Message> toReturn = new ArrayList<>();
    // Get all the active phone numbers so we can filter the user out of the list of targets
    // of any MMSes
    List<TelephonyHelper.LocalPhoneNumber> userPhoneNumbers = TelephonyHelper.getAllPhoneNumbers(context);
    try (Cursor myCursor = context.getContentResolver().query(uri, fetchColumns.toArray(ArrayUtils.EMPTY_STRING_ARRAY), selection, selectionArgs, sortOrder)) {
        if (myCursor != null && myCursor.moveToFirst()) {
            do {
                int transportTypeColumn = myCursor.getColumnIndex(getTransportTypeDiscriminatorColumn());
                TransportType transportType;
                if (transportTypeColumn < 0) {
                    // The column didn't actually exist. See https://issuetracker.google.com/issues/134592631
                    // Try to determine using other information
                    int messageBoxColumn = myCursor.getColumnIndex(Telephony.Mms.MESSAGE_BOX);
                    // MessageBoxColumn is defined for MMS only
                    boolean messageBoxExists = !myCursor.isNull(messageBoxColumn);
                    if (messageBoxExists) {
                        transportType = TransportType.MMS;
                    } else {
                        // There is room here for me to have made an assumption and we'll guess wrong
                        // The penalty is the user will potentially get some garbled data, so that's not too bad.
                        transportType = TransportType.SMS;
                    }
                } else {
                    String transportTypeString = myCursor.getString(transportTypeColumn);
                    if ("mms".equals(transportTypeString)) {
                        transportType = TransportType.MMS;
                    } else if ("sms".equals(transportTypeString)) {
                        transportType = TransportType.SMS;
                    } else {
                        Log.w("SMSHelper", "Skipping message with unknown TransportType: " + transportTypeString);
                        continue;
                    }
                }
                HashMap<String, String> messageInfo = new HashMap<>();
                for (int columnIdx = 0; columnIdx < myCursor.getColumnCount(); columnIdx++) {
                    String colName = myCursor.getColumnName(columnIdx);
                    String body = myCursor.getString(columnIdx);
                    messageInfo.put(colName, body);
                }
                try {
                    Message message;
                    if (transportType == TransportType.SMS) {
                        message = parseSMS(context, messageInfo);
                    } else if (transportType == TransportType.MMS) {
                        message = parseMMS(context, messageInfo, userPhoneNumbers);
                    } else {
                        // requires this line anyway
                        throw new UnsupportedOperationException("Unknown TransportType encountered");
                    }
                    toReturn.add(message);
                } catch (Exception e) {
                    // Swallow exceptions in case we get an error reading one message so that we
                    // might be able to read some of them
                    Log.e("SMSHelper", "Got an error reading a message of type " + transportType, e);
                }
            } while ((numberToGet == null || toReturn.size() < numberToGet) && myCursor.moveToNext());
        }
    } catch (SQLiteException | IllegalArgumentException e) {
        String[] unfilteredColumns = {};
        try (Cursor unfilteredColumnsCursor = context.getContentResolver().query(uri, null, null, null, null)) {
            if (unfilteredColumnsCursor != null) {
                unfilteredColumns = unfilteredColumnsCursor.getColumnNames();
            }
        }
        if (unfilteredColumns.length == 0) {
            throw new MessageAccessException(uri, e);
        } else {
            throw new MessageAccessException(unfilteredColumns, uri, e);
        }
    }
    return toReturn;
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Cursor(android.database.Cursor) SQLiteException(android.database.sqlite.SQLiteException) SuppressLint(android.annotation.SuppressLint) SQLiteException(android.database.sqlite.SQLiteException) JSONException(org.json.JSONException) IOException(java.io.IOException) NonNull(androidx.annotation.NonNull)

Example 42 with NonNull

use of androidx.annotation.NonNull in project kdeconnect-android by KDE.

the class TelephonyHelper method getAllPhoneNumbers.

/**
 * Try to get the phone number currently active on the phone
 *
 * Make sure that you have the READ_PHONE_STATE permission!
 *
 * Note that entries of the returned list might return null if the phone number is not known by the device
 */
@NonNull
public static List<LocalPhoneNumber> getAllPhoneNumbers(@NonNull Context context) throws SecurityException {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
        // Single-sim case
        // From https://stackoverflow.com/a/25131061/3723163
        // Android added support for multi-sim devices in Lollypop v5.1 (api 22)
        // See: https://developer.android.com/about/versions/android-5.1.html#multisim
        // There were vendor-specific implmentations before then, but those are very difficult to support
        // S/O Reference: https://stackoverflow.com/a/28571835/3723163
        TelephonyManager telephonyManager = ContextCompat.getSystemService(context, TelephonyManager.class);
        if (telephonyManager == null) {
            // I don't know why or when this happens...
            Log.w(LOGGING_TAG, "Could not get TelephonyManager");
            return Collections.emptyList();
        }
        LocalPhoneNumber phoneNumber = getPhoneNumber(telephonyManager);
        return Collections.singletonList(phoneNumber);
    } else {
        // Potentially multi-sim case
        SubscriptionManager subscriptionManager = ContextCompat.getSystemService(context, SubscriptionManager.class);
        if (subscriptionManager == null) {
            // I don't know why or when this happens...
            Log.w(LOGGING_TAG, "Could not get SubscriptionManager");
            return Collections.emptyList();
        }
        List<SubscriptionInfo> subscriptionInfos = subscriptionManager.getActiveSubscriptionInfoList();
        if (subscriptionInfos == null) {
            // This happens when there is no SIM card inserted
            Log.w(LOGGING_TAG, "Could not get SubscriptionInfos");
            return Collections.emptyList();
        }
        List<LocalPhoneNumber> phoneNumbers = new ArrayList<>(subscriptionInfos.size());
        for (SubscriptionInfo info : subscriptionInfos) {
            LocalPhoneNumber thisPhoneNumber = new LocalPhoneNumber(info.getNumber(), info.getSubscriptionId());
            phoneNumbers.add(thisPhoneNumber);
        }
        return phoneNumbers.stream().filter(localPhoneNumber -> localPhoneNumber.number != null).collect(Collectors.toList());
    }
}
Also used : Telephony(android.provider.Telephony) RequiresApi(androidx.annotation.RequiresApi) Context(android.content.Context) NonNull(androidx.annotation.NonNull) Uri(android.net.Uri) Collectors(java.util.stream.Collectors) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) SuppressLint(android.annotation.SuppressLint) List(java.util.List) Nullable(androidx.annotation.Nullable) SubscriptionManager(android.telephony.SubscriptionManager) TelephonyManager(android.telephony.TelephonyManager) OnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener) Build(android.os.Build) SubscriptionInfo(android.telephony.SubscriptionInfo) ContextCompat(androidx.core.content.ContextCompat) Collections(java.util.Collections) Log(android.util.Log) Cursor(android.database.Cursor) TelephonyManager(android.telephony.TelephonyManager) ArrayList(java.util.ArrayList) SubscriptionInfo(android.telephony.SubscriptionInfo) SubscriptionManager(android.telephony.SubscriptionManager) NonNull(androidx.annotation.NonNull)

Example 43 with NonNull

use of androidx.annotation.NonNull in project CustomActivityOnCrash by Ereza.

the class CustomActivityOnCrash method getAllErrorDetailsFromIntent.

/**
 * Given an Intent, returns several error details including the stack trace extra from the intent.
 *
 * @param context A valid context. Must not be null.
 * @param intent  The Intent. Must not be null.
 * @return The full error details.
 */
@NonNull
public static String getAllErrorDetailsFromIntent(@NonNull Context context, @NonNull Intent intent) {
    // I don't think that this needs localization because it's a development string...
    Date currentDate = new Date();
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
    // Get build date
    String buildDateAsString = getBuildDateAsString(context, dateFormat);
    // Get app version
    String versionName = getVersionName(context);
    String errorDetails = "";
    errorDetails += "Build version: " + versionName + " \n";
    if (buildDateAsString != null) {
        errorDetails += "Build date: " + buildDateAsString + " \n";
    }
    errorDetails += "Current date: " + dateFormat.format(currentDate) + " \n";
    // Added a space between line feeds to fix #18.
    // Ideally, we should not use this method at all... It is only formatted this way because of coupling with the default error activity.
    // We should move it to a method that returns a bean, and let anyone format it as they wish.
    errorDetails += "Device: " + getDeviceModelName() + " \n";
    errorDetails += "OS version: Android " + Build.VERSION.RELEASE + " (SDK " + Build.VERSION.SDK_INT + ") \n \n";
    errorDetails += "Stack trace:  \n";
    errorDetails += getStackTraceFromIntent(intent);
    String activityLog = getActivityLogFromIntent(intent);
    if (activityLog != null) {
        errorDetails += "\nUser actions: \n";
        errorDetails += activityLog;
    }
    return errorDetails;
}
Also used : SimpleDateFormat(java.text.SimpleDateFormat) DateFormat(java.text.DateFormat) SimpleDateFormat(java.text.SimpleDateFormat) Date(java.util.Date) NonNull(androidx.annotation.NonNull)

Example 44 with NonNull

use of androidx.annotation.NonNull in project banner by youth5201314.

the class Vp2FragmentRecyclerviewActivity method onCreate.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_vp2_fragment_recyclerview);
    ButterKnife.bind(this);
    viewPager2.setAdapter(new FragmentStateAdapter(this) {

        @NonNull
        @Override
        public Fragment createFragment(int position) {
            if (position == 0) {
                return BannerListFragment.newInstance(position);
            } else if (position == 1) {
                return BlankFragment.newInstance();
            } else {
                return BannerFragment.newInstance();
            }
        }

        @Override
        public int getItemCount() {
            return 3;
        }
    });
    new TabLayoutMediator(mTabLayout, viewPager2, (tab, position) -> {
        tab.setText("页面" + position);
    }).attach();
    mBanner.addBannerLifecycleObserver(this).setAdapter(new ImageAdapter(DataBean.getTestData())).setIntercept(false).setIndicator(new CircleIndicator(this));
}
Also used : R(com.test.banner.R) Bundle(android.os.Bundle) TabLayout(com.google.android.material.tabs.TabLayout) ButterKnife(butterknife.ButterKnife) NonNull(androidx.annotation.NonNull) TabLayoutMediator(com.test.banner.util.TabLayoutMediator) CircleIndicator(com.youth.banner.indicator.CircleIndicator) ViewPager2(androidx.viewpager2.widget.ViewPager2) AppCompatActivity(androidx.appcompat.app.AppCompatActivity) FragmentStateAdapter(androidx.viewpager2.adapter.FragmentStateAdapter) BindView(butterknife.BindView) DataBean(com.test.banner.bean.DataBean) Fragment(androidx.fragment.app.Fragment) Banner(com.youth.banner.Banner) ImageAdapter(com.test.banner.adapter.ImageAdapter) ImageAdapter(com.test.banner.adapter.ImageAdapter) NonNull(androidx.annotation.NonNull) CircleIndicator(com.youth.banner.indicator.CircleIndicator) TabLayoutMediator(com.test.banner.util.TabLayoutMediator) FragmentStateAdapter(androidx.viewpager2.adapter.FragmentStateAdapter) Fragment(androidx.fragment.app.Fragment)

Example 45 with NonNull

use of androidx.annotation.NonNull in project kdeconnect-android by KDE.

the class SmsMmsUtils method sendMessage.

/**
 * Sends SMS or MMS message.
 *
 * @param context       context in which the method is called.
 * @param textMessage   text body of the message to be sent.
 * @param addressList   List of addresses.
 * @param attachedFiles List of attachments. Pass empty list if none.
 * @param subID         Note that here subID is of type int and not long because klinker library requires it as int
 *                      I don't really know the exact reason why they implemented it as int instead of long
 */
public static void sendMessage(Context context, String textMessage, @NonNull List<SMSHelper.Attachment> attachedFiles, List<SMSHelper.Address> addressList, int subID) {
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
    boolean longTextAsMms = prefs.getBoolean(context.getString(R.string.set_long_text_as_mms), false);
    boolean groupMessageAsMms = prefs.getBoolean(context.getString(R.string.set_group_message_as_mms), true);
    int sendLongAsMmsAfter = Integer.parseInt(prefs.getString(context.getString(R.string.convert_to_mms_after), context.getString(R.string.convert_to_mms_after_default)));
    TelephonyHelper.LocalPhoneNumber sendingPhoneNumber;
    List<TelephonyHelper.LocalPhoneNumber> allPhoneNumbers = TelephonyHelper.getAllPhoneNumbers(context);
    Optional<TelephonyHelper.LocalPhoneNumber> maybeSendingPhoneNumber = allPhoneNumbers.stream().filter(localPhoneNumber -> localPhoneNumber.subscriptionID == subID).findAny();
    if (maybeSendingPhoneNumber.isPresent()) {
        sendingPhoneNumber = maybeSendingPhoneNumber.get();
    } else {
        if (allPhoneNumbers.isEmpty()) {
            // We were not able to get any phone number for the user's device
            // Use a null "dummy" number instead. This should behave the same as not setting
            // the FromAddress (below) since the default value there is null.
            // The only more-correct thing we could do here is query the user (maybe in a
            // persistent configuration) for their phone number(s).
            sendingPhoneNumber = new TelephonyHelper.LocalPhoneNumber(null, subID);
            Log.w(SENDING_MESSAGE, "We do not know *any* phone numbers for this device. " + "Attempting to send a message without knowing the local phone number is likely " + "to result in strange behavior, such as the message being sent to yourself, " + "or might entirely fail to send (or be received).");
        } else {
            // Pick an arbitrary phone number
            sendingPhoneNumber = allPhoneNumbers.get(0);
        }
        Log.w(SENDING_MESSAGE, "Unable to determine correct outgoing address for sub ID " + subID + ". Using " + sendingPhoneNumber);
    }
    if (sendingPhoneNumber.number != null) {
        // If the message is going to more than one target (to allow the user to send a message to themselves)
        if (addressList.size() > 1) {
            // Remove the user's phone number if present in the list of recipients
            addressList.removeIf(address -> sendingPhoneNumber.isMatchingPhoneNumber(address.address));
        }
    }
    try {
        Settings settings = new Settings();
        TelephonyHelper.ApnSetting apnSettings = TelephonyHelper.getPreferredApn(context, subID);
        if (apnSettings != null) {
            settings.setMmsc(apnSettings.getMmsc().toString());
            settings.setProxy(apnSettings.getMmsProxyAddressAsString());
            settings.setPort(Integer.toString(apnSettings.getMmsProxyPort()));
        } else {
            settings.setUseSystemSending(true);
        }
        settings.setSendLongAsMms(longTextAsMms);
        settings.setSendLongAsMmsAfter(sendLongAsMmsAfter);
        settings.setGroup(groupMessageAsMms);
        if (subID != -1) {
            settings.setSubscriptionId(subID);
        }
        Transaction transaction = new Transaction(context, settings);
        List<String> addresses = new ArrayList<>();
        for (SMSHelper.Address address : addressList) {
            addresses.add(address.toString());
        }
        Message message = new Message(textMessage, addresses.toArray(ArrayUtils.EMPTY_STRING_ARRAY));
        // If there are any attachment files add those into the message
        for (SMSHelper.Attachment attachedFile : attachedFiles) {
            byte[] file = Base64.decode(attachedFile.getBase64EncodedFile(), Base64.DEFAULT);
            String mimeType = attachedFile.getMimeType();
            String fileName = attachedFile.getUniqueIdentifier();
            message.addMedia(file, mimeType, fileName);
        }
        message.setFromAddress(sendingPhoneNumber.number);
        message.setSave(true);
        // This is the reason why there are separate branch handling for SMS and MMS.
        if (transaction.checkMMS(message)) {
            Log.v("", "Sending new MMS");
            // transaction.sendNewMessage(message, Transaction.NO_THREAD_ID);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
                sendMmsMessageNative(context, message, settings);
            } else {
                // Cross fingers and hope Klinker's library works for this case
                transaction.sendNewMessage(message, Transaction.NO_THREAD_ID);
            }
        } else {
            Log.v(SENDING_MESSAGE, "Sending new SMS");
            transaction.sendNewMessage(message, Transaction.NO_THREAD_ID);
        }
    // TODO: Notify other end
    } catch (Exception e) {
        // TODO: Notify other end
        Log.e(SENDING_MESSAGE, "Exception", e);
    }
}
Also used : Telephony(android.provider.Telephony) RequiresApi(androidx.annotation.RequiresApi) Bundle(android.os.Bundle) Message(com.klinker.android.send_message.Message) NonNull(androidx.annotation.NonNull) PduPart(com.google.android.mms.pdu_alt.PduPart) Uri(android.net.Uri) SmsManager(android.telephony.SmsManager) Random(java.util.Random) Utils(com.klinker.android.send_message.Utils) Transaction(com.klinker.android.send_message.Transaction) ByteArrayInputStream(java.io.ByteArrayInputStream) ContentResolver(android.content.ContentResolver) SmilXmlSerializer(com.android.mms.dom.smil.parser.SmilXmlSerializer) PreferenceManager(android.preference.PreferenceManager) Log(android.util.Log) SendReq(com.google.android.mms.pdu_alt.SendReq) IOUtils(org.apache.commons.io.IOUtils) List(java.util.List) ContentType(com.google.android.mms.ContentType) SmilHelper(com.google.android.mms.smil.SmilHelper) Optional(java.util.Optional) ContentValues(android.content.ContentValues) MultimediaMessagePdu(com.google.android.mms.pdu_alt.MultimediaMessagePdu) SMSHelper(org.kde.kdeconnect.Helpers.SMSHelper) Context(android.content.Context) ByteArrayOutputStream(java.io.ByteArrayOutputStream) BitmapFactory(android.graphics.BitmapFactory) ArrayUtils(org.apache.commons.lang3.ArrayUtils) MMSPart(com.google.android.mms.MMSPart) TelephonyHelper(org.kde.kdeconnect.Helpers.TelephonyHelper) R(org.kde.kdeconnect_tp.R) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Build(android.os.Build) InvalidHeaderValueException(com.google.android.mms.InvalidHeaderValueException) PduHeaders(com.google.android.mms.pdu_alt.PduHeaders) NetworkPacket(org.kde.kdeconnect.NetworkPacket) RetrieveConf(com.google.android.mms.pdu_alt.RetrieveConf) EncodedStringValue(com.google.android.mms.pdu_alt.EncodedStringValue) FileOutputStream(java.io.FileOutputStream) TextUtils(android.text.TextUtils) IOException(java.io.IOException) File(java.io.File) SharedPreferences(android.content.SharedPreferences) Bitmap(android.graphics.Bitmap) Base64(android.util.Base64) CharacterSets(com.google.android.mms.pdu_alt.CharacterSets) PduComposer(com.google.android.mms.pdu_alt.PduComposer) Settings(com.klinker.android.send_message.Settings) PduBody(com.google.android.mms.pdu_alt.PduBody) ContentUris(android.content.ContentUris) InputStream(java.io.InputStream) Message(com.klinker.android.send_message.Message) SharedPreferences(android.content.SharedPreferences) ArrayList(java.util.ArrayList) SMSHelper(org.kde.kdeconnect.Helpers.SMSHelper) InvalidHeaderValueException(com.google.android.mms.InvalidHeaderValueException) IOException(java.io.IOException) Transaction(com.klinker.android.send_message.Transaction) TelephonyHelper(org.kde.kdeconnect.Helpers.TelephonyHelper) Settings(com.klinker.android.send_message.Settings)

Aggregations

NonNull (androidx.annotation.NonNull)1200 View (android.view.View)192 ArrayList (java.util.ArrayList)154 Context (android.content.Context)128 Nullable (androidx.annotation.Nullable)128 TextView (android.widget.TextView)118 Intent (android.content.Intent)115 List (java.util.List)110 Recipient (org.thoughtcrime.securesms.recipients.Recipient)109 IOException (java.io.IOException)103 Bundle (android.os.Bundle)102 WorkerThread (androidx.annotation.WorkerThread)94 LayoutInflater (android.view.LayoutInflater)89 RecipientId (org.thoughtcrime.securesms.recipients.RecipientId)82 AlertDialog (androidx.appcompat.app.AlertDialog)77 Log (org.signal.core.util.logging.Log)76 Cursor (android.database.Cursor)68 ViewGroup (android.view.ViewGroup)65 LinkedList (java.util.LinkedList)64 Stream (com.annimon.stream.Stream)62