Merge pull request #3215 from deltachat/adb/issue-1791

stop using jcenter
This commit is contained in:
Asiel Díaz Benítez
2024-08-14 12:24:45 +02:00
committed by GitHub
9 changed files with 2042 additions and 62 deletions
+7 -9
View File
@@ -7,11 +7,9 @@ repositories {
google()
mavenCentral()
maven {
// Used only for PhotoView
url "https://www.jitpack.io"
name 'JitPack Github wrapper'
}
jcenter()
}
android {
@@ -35,7 +33,7 @@ android {
applicationId "com.b44t.messenger"
multiDexEnabled true
minSdkVersion 16
minSdkVersion 19
targetSdkVersion 33
vectorDrawables.useSupportLibrary = true
@@ -164,10 +162,11 @@ dependencies {
implementation 'androidx.work:work-runtime:2.8.1'
implementation 'androidx.emoji2:emoji2-emojipicker:1.4.0'
implementation 'com.google.guava:guava:29.0-android'
implementation 'com.google.android.exoplayer:exoplayer-core:2.9.6' // plays video and audio
implementation 'com.google.android.exoplayer:exoplayer-ui:2.9.6'
implementation 'com.google.android.exoplayer:exoplayer-core:2.19.1' // plays video and audio
implementation 'com.google.android.exoplayer:exoplayer-ui:2.19.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.journeyapps:zxing-android-embedded:3.4.0' // QR Code scanner
implementation 'com.google.zxing:core:3.3.0' // fixed version to support SDK<24
implementation ('com.journeyapps:zxing-android-embedded:4.3.0') { transitive = false } // QR Code scanner
implementation 'com.fasterxml.jackson.core:jackson-databind:2.11.1' // used as JSON library
implementation 'com.google.code.gson:gson:2.9.1' // used as JSON library. Don't upgrade to 2.10.1: https://github.com/deltachat/deltachat-android/pull/2610
implementation "me.leolin:ShortcutBadger:1.1.16" // display messagecount on the home screen icon.
@@ -182,16 +181,15 @@ dependencies {
implementation 'com.pnikosis:materialish-progress:1.5' // used only in the "Progress Wheel" in Share Activity.
implementation 'com.soundcloud.android:android-crop:1.0.1@aar' // used for profile and group avatar selection in Android SDK<19
implementation 'com.nineoldandroids:library:2.4.0' // DEPRECATED! Used to slide in the half-camera.
implementation 'mobi.upod:time-duration-picker:1.1.3' // Used to pick the time for inactivity.
implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1' // number of unread messages,
implementation 'com.github.amulyakhare:TextDrawable:558677ea31' // number of unread messages,
// the one-letter circle for the contacts (when there is not avatar) and a white background.
implementation 'com.googlecode.mp4parser:isoparser:1.0.6' // MP4 recoding; upgrading eg. to 1.1.22 breaks recoding, however, i have not investigated further, just reset to 1.0.6
implementation ('com.davemorrissey.labs:subsampling-scale-image-view:3.6.0') { // for the zooming on photos / media
exclude group: 'com.android.support', module: 'support-annotations'
}
implementation 'com.annimon:stream:1.1.8' // brings future java streams api to SDK Version < 24
implementation 'com.codewaves.stickyheadergrid:stickyheadergrid:0.9.4' // glues the current time segment text in the gallery to the top.
implementation 'com.getkeepsafe.relinker:relinker:1.4.4' // needed to avoid safe-content-resolver-v14 trying to fetch older non-existing version
// Replacement for ContentResolver
// that protects against the Surreptitious Sharing attack.
// <https://github.com/cketti/SafeContentResolver>
@@ -0,0 +1,612 @@
package com.codewaves.stickyheadergrid;
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.security.InvalidParameterException;
import java.util.ArrayList;
/**
* Created by Sergej Kravcenko on 4/24/2017.
* Copyright (c) 2017 Sergej Kravcenko
*/
@SuppressWarnings({"unused", "WeakerAccess"})
public abstract class StickyHeaderGridAdapter extends RecyclerView.Adapter<StickyHeaderGridAdapter.ViewHolder> {
public static final String TAG = "StickyHeaderGridAdapter";
public static final int TYPE_HEADER = 0;
public static final int TYPE_ITEM = 1;
private ArrayList<Section> mSections;
private int[] mSectionIndices;
private int mTotalItemNumber;
@SuppressWarnings("WeakerAccess")
public static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
}
public boolean isHeader() {
return false;
}
public int getSectionItemViewType() {
return StickyHeaderGridAdapter.externalViewType(getItemViewType());
}
}
public static class ItemViewHolder extends ViewHolder {
public ItemViewHolder(View itemView) {
super(itemView);
}
}
public static class HeaderViewHolder extends ViewHolder {
public HeaderViewHolder(View itemView) {
super(itemView);
}
@Override
public boolean isHeader() {
return true;
}
}
private static class Section {
private int position;
private int itemNumber;
private int length;
}
private void calculateSections() {
mSections = new ArrayList<>();
int total = 0;
int sectionCount = getSectionCount();
for (int s = 0; s < sectionCount; s++) {
final Section section = new Section();
section.position = total;
section.itemNumber = getSectionItemCount(s);
section.length = section.itemNumber + 1;
mSections.add(section);
total += section.length;
}
mTotalItemNumber = total;
total = 0;
mSectionIndices = new int[mTotalItemNumber];
for (int s = 0; s < sectionCount; s++) {
final Section section = mSections.get(s);
for (int i = 0; i < section.length; i++) {
mSectionIndices[total + i] = s;
}
total += section.length;
}
}
protected int getItemViewInternalType(int position) {
final int section = getAdapterPositionSection(position);
final Section sectionObject = mSections.get(section);
final int sectionPosition = position - sectionObject.position;
return getItemViewInternalType(section, sectionPosition);
}
private int getItemViewInternalType(int section, int position) {
return position == 0 ? TYPE_HEADER : TYPE_ITEM;
}
static private int internalViewType(int type) {
return type & 0xFF;
}
static private int externalViewType(int type) {
return type >> 8;
}
@Override
final public int getItemCount() {
if (mSections == null) {
calculateSections();
}
return mTotalItemNumber;
}
@NonNull
@Override
final public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
final int internalType = internalViewType(viewType);
final int externalType = externalViewType(viewType);
switch (internalType) {
case TYPE_HEADER:
return onCreateHeaderViewHolder(parent, externalType);
case TYPE_ITEM:
return onCreateItemViewHolder(parent, externalType);
default:
throw new InvalidParameterException("Invalid viewType: " + viewType);
}
}
@Override
final public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
if (mSections == null) {
calculateSections();
}
final int section = mSectionIndices[position];
final int internalType = internalViewType(holder.getItemViewType());
final int externalType = externalViewType(holder.getItemViewType());
switch (internalType) {
case TYPE_HEADER:
onBindHeaderViewHolder((HeaderViewHolder)holder, section);
break;
case TYPE_ITEM:
final ItemViewHolder itemHolder = (ItemViewHolder)holder;
final int offset = getItemSectionOffset(section, position);
onBindItemViewHolder((ItemViewHolder)holder, section, offset);
break;
default:
throw new InvalidParameterException("invalid viewType: " + internalType);
}
}
@Override
final public int getItemViewType(int position) {
final int section = getAdapterPositionSection(position);
final Section sectionObject = mSections.get(section);
final int sectionPosition = position - sectionObject.position;
final int internalType = getItemViewInternalType(section, sectionPosition);
int externalType = 0;
switch (internalType) {
case TYPE_HEADER:
externalType = getSectionHeaderViewType(section);
break;
case TYPE_ITEM:
externalType = getSectionItemViewType(section, sectionPosition - 1);
break;
}
return ((externalType & 0xFF) << 8) | (internalType & 0xFF);
}
// Helpers
private int getItemSectionHeaderPosition(int position) {
return getSectionHeaderPosition(getAdapterPositionSection(position));
}
private int getAdapterPosition(int section, int offset) {
if (mSections == null) {
calculateSections();
}
if (section < 0) {
throw new IndexOutOfBoundsException("section " + section + " < 0");
}
if (section >= mSections.size()) {
throw new IndexOutOfBoundsException("section " + section + " >=" + mSections.size());
}
final Section sectionObject = mSections.get(section);
return sectionObject.position + offset;
}
/**
* Given a <code>section</code> and an adapter <code>position</code> get the offset of an item
* inside <code>section</code>.
*
* @param section section to query
* @param position adapter position
* @return The item offset inside the section.
*/
public int getItemSectionOffset(int section, int position) {
if (mSections == null) {
calculateSections();
}
if (section < 0) {
throw new IndexOutOfBoundsException("section " + section + " < 0");
}
if (section >= mSections.size()) {
throw new IndexOutOfBoundsException("section " + section + " >=" + mSections.size());
}
final Section sectionObject = mSections.get(section);
final int localPosition = position - sectionObject.position;
if (localPosition >= sectionObject.length) {
throw new IndexOutOfBoundsException("localPosition: " + localPosition + " >=" + sectionObject.length);
}
return localPosition - 1;
}
/**
* Returns the section index having item or header with provided
* provider <code>position</code>.
*
* @param position adapter position
* @return The section containing provided adapter position.
*/
public int getAdapterPositionSection(int position) {
if (mSections == null) {
calculateSections();
}
if (getItemCount() == 0) {
return NO_POSITION;
}
if (position < 0) {
throw new IndexOutOfBoundsException("position " + position + " < 0");
}
if (position >= getItemCount()) {
throw new IndexOutOfBoundsException("position " + position + " >=" + getItemCount());
}
return mSectionIndices[position];
}
/**
* Returns the adapter position for given <code>section</code> header. Use
* this only for {@link RecyclerView#scrollToPosition(int)} or similar functions.
* Never directly manipulate adapter items using this position.
*
* @param section section to query
* @return The adapter position.
*/
public int getSectionHeaderPosition(int section) {
return getAdapterPosition(section, 0);
}
/**
* Returns the adapter position for given <code>section</code> and
* <code>offset</code>. Use this only for {@link RecyclerView#scrollToPosition(int)}
* or similar functions. Never directly manipulate adapter items using this position.
*
* @param section section to query
* @param position item position inside the <code>section</code>
* @return The adapter position.
*/
public int getSectionItemPosition(int section, int position) {
return getAdapterPosition(section, position + 1);
}
// Overrides
/**
* Returns the total number of sections in the data set held by the adapter.
*
* @return The total number of section in this adapter.
*/
public int getSectionCount() {
return 0;
}
/**
* Returns the number of items in the <code>section</code>.
*
* @param section section to query
* @return The total number of items in the <code>section</code>.
*/
public int getSectionItemCount(int section) {
return 0;
}
/**
* Return the view type of the <code>section</code> header for the purposes
* of view recycling.
*
* <p>The default implementation of this method returns 0, making the assumption of
* a single view type for the headers. Unlike ListView adapters, types need not
* be contiguous. Consider using id resources to uniquely identify item view types.
*
* @param section section to query
* @return integer value identifying the type of the view needed to represent the header in
* <code>section</code>. Type codes need not be contiguous.
*/
public int getSectionHeaderViewType(int section) {
return 0;
}
/**
* Return the view type of the item at <code>position</code> in <code>section</code> for
* the purposes of view recycling.
*
* <p>The default implementation of this method returns 0, making the assumption of
* a single view type for the adapter. Unlike ListView adapters, types need not
* be contiguous. Consider using id resources to uniquely identify item view types.
*
* @param section section to query
* @param offset section position to query
* @return integer value identifying the type of the view needed to represent the item at
* <code>position</code> in <code>section</code>. Type codes need not be
* contiguous.
*/
public int getSectionItemViewType(int section, int offset) {
return 0;
}
/**
* Returns true if header in <code>section</code> is sticky.
*
* @param section section to query
* @return true if <code>section</code> header is sticky.
*/
public boolean isSectionHeaderSticky(int section) {
return true;
}
/**
* Called when RecyclerView needs a new {@link HeaderViewHolder} of the given type to represent
* a header.
* <p>
* This new HeaderViewHolder should be constructed with a new View that can represent the headers
* of the given type. You can either create a new View manually or inflate it from an XML
* layout file.
* <p>
* The new HeaderViewHolder will be used to display items of the adapter using
* {@link #onBindHeaderViewHolder(HeaderViewHolder, int)}. Since it will be re-used to display
* different items in the data set, it is a good idea to cache references to sub views of
* the View to avoid unnecessary {@link View#findViewById(int)} calls.
*
* @param parent The ViewGroup into which the new View will be added after it is bound to
* an adapter position.
* @param headerType The view type of the new View.
*
* @return A new ViewHolder that holds a View of the given view type.
* @see #getSectionHeaderViewType(int)
* @see #onBindHeaderViewHolder(HeaderViewHolder, int)
*/
public abstract HeaderViewHolder onCreateHeaderViewHolder(ViewGroup parent, int headerType);
/**
* Called when RecyclerView needs a new {@link ItemViewHolder} of the given type to represent
* an item.
* <p>
* This new ViewHolder should be constructed with a new View that can represent the items
* of the given type. You can either create a new View manually or inflate it from an XML
* layout file.
* <p>
* The new ViewHolder will be used to display items of the adapter using
* {@link #onBindItemViewHolder(ItemViewHolder, int, int)}. Since it will be re-used to display
* different items in the data set, it is a good idea to cache references to sub views of
* the View to avoid unnecessary {@link View#findViewById(int)} calls.
*
* @param parent The ViewGroup into which the new View will be added after it is bound to
* an adapter position.
* @param itemType The view type of the new View.
*
* @return A new ViewHolder that holds a View of the given view type.
* @see #getSectionItemViewType(int, int)
* @see #onBindItemViewHolder(ItemViewHolder, int, int)
*/
public abstract ItemViewHolder onCreateItemViewHolder(ViewGroup parent, int itemType);
/**
* Called by RecyclerView to display the data at the specified position. This method should
* update the contents of the {@link HeaderViewHolder#itemView} to reflect the header at the given
* position.
* <p>
* Note that unlike {@link android.widget.ListView}, RecyclerView will not call this method
* again if the position of the header changes in the data set unless the header itself is
* invalidated or the new position cannot be determined. For this reason, you should only
* use the <code>section</code> parameter while acquiring the
* related header data inside this method and should not keep a copy of it. If you need the
* position of a header later on (e.g. in a click listener), use
* {@link HeaderViewHolder#getAdapterPosition()} which will have the updated adapter
* position. Then you can use {@link #getAdapterPositionSection(int)} to get section index.
*
*
* @param viewHolder The ViewHolder which should be updated to represent the contents of the
* header at the given position in the data set.
* @param section The index of the section.
*/
public abstract void onBindHeaderViewHolder(HeaderViewHolder viewHolder, int section);
/**
* Called by RecyclerView to display the data at the specified position. This method should
* update the contents of the {@link ItemViewHolder#itemView} to reflect the item at the given
* position.
* <p>
* Note that unlike {@link android.widget.ListView}, RecyclerView will not call this method
* again if the position of the item changes in the data set unless the item itself is
* invalidated or the new position cannot be determined. For this reason, you should only
* use the <code>offset</code> and <code>section</code> parameters while acquiring the
* related data item inside this method and should not keep a copy of it. If you need the
* position of an item later on (e.g. in a click listener), use
* {@link ItemViewHolder#getAdapterPosition()} which will have the updated adapter
* position. Then you can use {@link #getAdapterPositionSection(int)} and
* {@link #getItemSectionOffset(int, int)}
*
*
* @param viewHolder The ViewHolder which should be updated to represent the contents of the
* item at the given position in the data set.
* @param section The index of the section.
* @param offset The position of the item within the section.
*/
public abstract void onBindItemViewHolder(ItemViewHolder viewHolder, int section, int offset);
// Notify
/**
* Notify any registered observers that the data set has changed.
*
* <p>There are two different classes of data change events, item changes and structural
* changes. Item changes are when a single item has its data updated but no positional
* changes have occurred. Structural changes are when items are inserted, removed or moved
* within the data set.</p>
*
* <p>This event does not specify what about the data set has changed, forcing
* any observers to assume that all existing items and structure may no longer be valid.
* LayoutManagers will be forced to fully rebind and relayout all visible views.</p>
*
* <p><code>RecyclerView</code> will attempt to synthesize visible structural change events
* for adapters that report that they have {@link #hasStableIds() stable IDs} when
* this method is used. This can help for the purposes of animation and visual
* object persistence but individual item views will still need to be rebound
* and relaid out.</p>
*
* <p>If you are writing an adapter it will always be more efficient to use the more
* specific change events if you can. Rely on <code>notifyDataSetChanged()</code>
* as a last resort.</p>
*
* @see #notifySectionDataSetChanged(int)
* @see #notifySectionHeaderChanged(int)
* @see #notifySectionItemChanged(int, int)
* @see #notifySectionInserted(int)
* @see #notifySectionItemInserted(int, int)
* @see #notifySectionItemRangeInserted(int, int, int)
* @see #notifySectionRemoved(int)
* @see #notifySectionItemRemoved(int, int)
* @see #notifySectionItemRangeRemoved(int, int, int)
*/
public void notifyAllSectionsDataSetChanged() {
calculateSections();
notifyDataSetChanged();
}
public void notifySectionDataSetChanged(int section) {
calculateSections();
if (mSections == null) {
notifyAllSectionsDataSetChanged();
}
else {
final Section sectionObject = mSections.get(section);
notifyItemRangeChanged(sectionObject.position, sectionObject.length);
}
}
public void notifySectionHeaderChanged(int section) {
calculateSections();
if (mSections == null) {
notifyAllSectionsDataSetChanged();
}
else {
final Section sectionObject = mSections.get(section);
notifyItemRangeChanged(sectionObject.position, 1);
}
}
public void notifySectionItemChanged(int section, int position) {
calculateSections();
if (mSections == null) {
notifyAllSectionsDataSetChanged();
}
else {
final Section sectionObject = mSections.get(section);
if (position >= sectionObject.itemNumber) {
throw new IndexOutOfBoundsException("Invalid index " + position + ", size is " + sectionObject.itemNumber);
}
notifyItemChanged(sectionObject.position + position + 1);
}
}
public void notifySectionInserted(int section) {
calculateSections();
if (mSections == null) {
notifyAllSectionsDataSetChanged();
}
else {
final Section sectionObject = mSections.get(section);
notifyItemRangeInserted(sectionObject.position, sectionObject.length);
}
}
public void notifySectionItemInserted(int section, int position) {
calculateSections();
if (mSections == null) {
notifyAllSectionsDataSetChanged();
}
else {
final Section sectionObject = mSections.get(section);
if (position < 0 || position >= sectionObject.itemNumber) {
throw new IndexOutOfBoundsException("Invalid index " + position + ", size is " + sectionObject.itemNumber);
}
notifyItemInserted(sectionObject.position + position + 1);
}
}
public void notifySectionItemRangeInserted(int section, int position, int count) {
calculateSections();
if (mSections == null) {
notifyAllSectionsDataSetChanged();
}
else {
final Section sectionObject = mSections.get(section);
if (position < 0 || position >= sectionObject.itemNumber) {
throw new IndexOutOfBoundsException("Invalid index " + position + ", size is " + sectionObject.itemNumber);
}
if (position + count > sectionObject.itemNumber) {
throw new IndexOutOfBoundsException("Invalid index " + (position + count) + ", size is " + sectionObject.itemNumber);
}
notifyItemRangeInserted(sectionObject.position + position + 1, count);
}
}
public void notifySectionRemoved(int section) {
if (mSections == null) {
calculateSections();
notifyAllSectionsDataSetChanged();
}
else {
final Section sectionObject = mSections.get(section);
calculateSections();
notifyItemRangeRemoved(sectionObject.position, sectionObject.length);
}
}
public void notifySectionItemRemoved(int section, int position) {
if (mSections == null) {
calculateSections();
notifyAllSectionsDataSetChanged();
}
else {
final Section sectionObject = mSections.get(section);
if (position < 0 || position >= sectionObject.itemNumber) {
throw new IndexOutOfBoundsException("Invalid index " + position + ", size is " + sectionObject.itemNumber);
}
calculateSections();
notifyItemRemoved(sectionObject.position + position + 1);
}
}
public void notifySectionItemRangeRemoved(int section, int position, int count) {
if (mSections == null) {
calculateSections();
notifyAllSectionsDataSetChanged();
}
else {
final Section sectionObject = mSections.get(section);
if (position < 0 || position >= sectionObject.itemNumber) {
throw new IndexOutOfBoundsException("Invalid index " + position + ", size is " + sectionObject.itemNumber);
}
if (position + count > sectionObject.itemNumber) {
throw new IndexOutOfBoundsException("Invalid index " + (position + count) + ", size is " + sectionObject.itemNumber);
}
calculateSections();
notifyItemRangeRemoved(sectionObject.position + position + 1, count);
}
}
}
File diff suppressed because it is too large Load Diff
@@ -17,7 +17,6 @@ import java.util.HashSet;
import static org.thoughtcrime.securesms.util.MediaUtil.getMimeType;
import de.cketti.safecontentresolver.SafeContentResolver;
import de.cketti.safecontentresolver.SafeContentResolverCompat;
public class ResolveMediaTask extends AsyncTask<Uri, Void, Uri> {
@@ -50,7 +49,7 @@ public class ResolveMediaTask extends AsyncTask<Uri, Void, Uri> {
String fileName = null;
Long fileSize = null;
SafeContentResolver safeContentResolver = SafeContentResolverCompat.newInstance(contextRef.get());
SafeContentResolver safeContentResolver = SafeContentResolver.newInstance(contextRef.get());
inputStream = safeContentResolver.openInputStream(uri);
if (inputStream == null) {
@@ -16,16 +16,16 @@ import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.LoadControl;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.audio.AudioAttributes;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
@@ -76,10 +76,13 @@ public class AudioSlidePlayer {
public void requestDuration() {
try {
LoadControl loadControl = new DefaultLoadControl.Builder().setBufferDurationsMs(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE).createDefaultLoadControl();
durationCalculator = ExoPlayerFactory.newSimpleInstance(context, new DefaultRenderersFactory(context), new DefaultTrackSelector(), loadControl);
LoadControl loadControl = new DefaultLoadControl.Builder().setBufferDurationsMs(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE).build();
durationCalculator = new SimpleExoPlayer.Builder(context, new DefaultRenderersFactory(context))
.setTrackSelector(new DefaultTrackSelector(context))
.setLoadControl(loadControl)
.build();
durationCalculator.setPlayWhenReady(false);
durationCalculator.addListener(new Player.EventListener() {
durationCalculator.addListener(new Player.Listener() {
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == Player.STATE_READY) {
@@ -113,16 +116,19 @@ public class AudioSlidePlayer {
throw new IOException("Slide has no URI!");
}
LoadControl loadControl = new DefaultLoadControl.Builder().setBufferDurationsMs(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE).createDefaultLoadControl();
this.mediaPlayer = ExoPlayerFactory.newSimpleInstance(context, new DefaultRenderersFactory(context), new DefaultTrackSelector(), loadControl);
LoadControl loadControl = new DefaultLoadControl.Builder().setBufferDurationsMs(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE).build();
this.mediaPlayer = new SimpleExoPlayer.Builder(context, new DefaultRenderersFactory(context))
.setTrackSelector(new DefaultTrackSelector(context))
.setLoadControl(loadControl)
.build();
mediaPlayer.prepare(createMediaSource(slide.getUri()));
mediaPlayer.setPlayWhenReady(true);
mediaPlayer.setAudioAttributes(new AudioAttributes.Builder()
.setContentType(earpiece ? C.CONTENT_TYPE_SPEECH : C.CONTENT_TYPE_MUSIC)
.setContentType(earpiece ? C.AUDIO_CONTENT_TYPE_SPEECH : C.AUDIO_CONTENT_TYPE_MUSIC)
.setUsage(earpiece ? C.USAGE_VOICE_COMMUNICATION : C.USAGE_MEDIA)
.build());
mediaPlayer.addListener(new Player.EventListener() {
.build(), false);
mediaPlayer.addListener(new Player.Listener() {
boolean started = false;
@@ -171,7 +177,7 @@ public class AudioSlidePlayer {
}
@Override
public void onPlayerError(ExoPlaybackException error) {
public void onPlayerError(PlaybackException error) {
Log.w(TAG, "MediaPlayer Error: " + error);
synchronized (AudioSlidePlayer.this) {
@@ -194,9 +200,8 @@ public class AudioSlidePlayer {
AttachmentDataSourceFactory attachmentDataSourceFactory = new AttachmentDataSourceFactory(defaultDataSourceFactory);
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true);
return new ExtractorMediaSource.Factory(attachmentDataSourceFactory)
.setExtractorsFactory(extractorsFactory)
.createMediaSource(uri);
return new ProgressiveMediaSource.Factory(attachmentDataSourceFactory, extractorsFactory)
.createMediaSource(MediaItem.fromUri(uri));
}
public synchronized void stop() {
@@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.qr;
import android.app.Activity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -106,8 +107,11 @@ public class QrScanFragment extends Fragment {
// which makes _showing_ the QR-code impossible if scanning goes wrong.
// therefore, we only show a non-disturbing error here.
@Override
protected void displayFrameworkBugMessageAndExit() {
Toast.makeText(myActivity, R.string.zxing_msg_camera_framework_bug, Toast.LENGTH_SHORT).show();
protected void displayFrameworkBugMessageAndExit(String message) {
if (TextUtils.isEmpty(message)) {
message = myActivity.getString(R.string.zxing_msg_camera_framework_bug);
}
Toast.makeText(myActivity, message, Toast.LENGTH_SHORT).show();
}
}
@@ -17,27 +17,26 @@
package org.thoughtcrime.securesms.video;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.util.AttributeSet;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.LoadControl;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.ui.SimpleExoPlayerView;
import com.google.android.exoplayer2.ui.PlayerView;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
@@ -49,7 +48,7 @@ import org.thoughtcrime.securesms.video.exo.AttachmentDataSourceFactory;
public class VideoPlayer extends FrameLayout {
@Nullable private final SimpleExoPlayerView exoView;
@Nullable private final PlayerView exoView;
@Nullable private SimpleExoPlayer exoPlayer;
@Nullable private Window window;
@@ -93,12 +92,15 @@ public class VideoPlayer extends FrameLayout {
private void setExoViewSource(@NonNull VideoSlide videoSource, boolean autoplay)
{
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter.Builder(getContext()).build();
TrackSelector trackSelector = new DefaultTrackSelector(getContext());
LoadControl loadControl = new DefaultLoadControl();
exoPlayer = ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector, loadControl);
exoPlayer = new SimpleExoPlayer.Builder(getContext())
.setTrackSelector(trackSelector)
.setBandwidthMeter(bandwidthMeter)
.setLoadControl(loadControl)
.build();
exoPlayer.addListener(new ExoPlayerListener(window));
//noinspection ConstantConditions
exoView.setPlayer(exoPlayer);
@@ -107,13 +109,14 @@ public class VideoPlayer extends FrameLayout {
AttachmentDataSourceFactory attachmentDataSourceFactory = new AttachmentDataSourceFactory(defaultDataSourceFactory);
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
MediaSource mediaSource = new ExtractorMediaSource(videoSource.getUri(), attachmentDataSourceFactory, extractorsFactory, null, null);
MediaSource mediaSource = new ProgressiveMediaSource.Factory(attachmentDataSourceFactory, extractorsFactory)
.createMediaSource(MediaItem.fromUri(videoSource.getUri()));
exoPlayer.prepare(mediaSource);
exoPlayer.setPlayWhenReady(autoplay);
}
private static class ExoPlayerListener implements Player.EventListener {
private static class ExoPlayerListener implements Player.Listener {
private final Window window;
ExoPlayerListener(Window window) {
-14
View File
@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.exoplayer2.ui.SimpleExoPlayerView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"/>
</FrameLayout>
+7 -6
View File
@@ -4,10 +4,11 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<VideoView android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"/>
<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"/>
</FrameLayout>
</FrameLayout>