Skip to content

Commit 6c80846

Browse files
committed
New model manager implementation pt. 2
1 parent a9e03e4 commit 6c80846

22 files changed

Lines changed: 1115 additions & 188 deletions

app/src/main/java/nie/translator/rtranslator/Global.java

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,6 @@ public void onCreate() {
111111
super.onCreate();
112112
mainHandler = new Handler(Looper.getMainLooper());
113113
recentPeersDataManager = new RecentPeersDataManager(this);
114-
PRDownloaderConfig config = PRDownloaderConfig.newBuilder()
115-
.setDatabaseEnabled(false)
116-
.build();
117-
PRDownloader.initialize(getApplicationContext(), config);
118114
//initializeBluetoothCommunicator();
119115
getMicSensitivity();
120116
createNotificationChannel();
@@ -742,25 +738,59 @@ private void createNotificationChannel(){
742738
/**
743739
* Returns the total RAM size of the device in MB
744740
*/
745-
public long getTotalRamSize(){
741+
public int getTotalRamSize(){
746742
ActivityManager actManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
747743
ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
748744
actManager.getMemoryInfo(memInfo);
749745
long totalMemory = memInfo.totalMem / 1000000L;
750746
android.util.Log.i("memory", "Total memory: " + totalMemory);
751-
return totalMemory;
747+
return (int) totalMemory;
752748
}
753749

754750
/**
755751
* Returns the available RAM size of the device in MB
756752
*/
757-
public long getAvailableRamSize(){
753+
public int getAvailableRamSize(){
758754
ActivityManager actManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
759755
ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
760756
actManager.getMemoryInfo(memInfo);
761-
long totalMemory = memInfo.availMem;
762-
android.util.Log.i("memory", "Total memory: " + totalMemory);
763-
return totalMemory / 1000000L;
757+
long availableMemory = memInfo.availMem;
758+
android.util.Log.i("memory", "Total memory: " + availableMemory);
759+
return (int) (availableMemory / 1000000);
760+
}
761+
762+
/**
763+
* Returns (in MB) the absolute maximum native RAM allocatable by forcing the OS
764+
* to kill all other killable processes.
765+
*/
766+
public int getMaxAllocatableRAM() {
767+
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
768+
if (activityManager == null) return 0;
769+
770+
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
771+
activityManager.getMemoryInfo(memoryInfo);
772+
773+
// Total physical RAM available to the OS (already excludes GPU-reserved RAM)
774+
long totalRam = memoryInfo.totalMem;
775+
776+
// Android doesn't have an API that shows the max amount of RAM available for native allocations before a crash occurs,
777+
// so the best way (also hinted here https://developer.android.com/games/optimize/memory-allocation#conservative-memory-budgets)
778+
// is to use a percentage of the total RAM between 50% and 25% as a hard limit of native RAM usage for a single app.
779+
double maxPercentage = 0.45;
780+
781+
// The absolute theoretical maximum you can allocate before the OS targets YOU
782+
long maxAllocatable = (long) (totalRam - (totalRam*maxPercentage)) / 1000000L;
783+
784+
// Return the result, ensuring we don't return a negative number on heavily constrained devices
785+
return (int) Math.max(0, maxAllocatable);
786+
}
787+
788+
public int getRamThreshold(){
789+
ActivityManager actManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
790+
ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
791+
actManager.getMemoryInfo(memInfo);
792+
long threshold = memInfo.threshold;
793+
return (int) (threshold / 1000000);
764794
}
765795

766796
/**

app/src/main/java/nie/translator/rtranslator/access/DownloadFragment.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import android.view.View;
3333
import android.view.ViewGroup;
3434
import android.widget.ImageButton;
35-
import android.widget.ProgressBar;
3635
import android.widget.TextView;
3736

3837
import com.google.android.material.progressindicator.LinearProgressIndicator;
@@ -122,7 +121,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
122121
downloadErrorText = view.findViewById(R.id.text_error_download);
123122
transferErrorText = view.findViewById(R.id.text_error_transfer);
124123
storageWarningText = view.findViewById(R.id.text_error_storage);
125-
progressBar = view.findViewById(R.id.progressBar);
124+
progressBar = view.findViewById(R.id.barRam);
126125
progressDescriptionText = view.findViewById(R.id.progress_description);
127126
pauseButton = view.findViewById(R.id.pauseButton);
128127
pauseButton.setTag("iconCancel");

app/src/main/java/nie/translator/rtranslator/access/DownloadFragment2.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
8787
downloadErrorText = view.findViewById(R.id.text_error_download);
8888
transferErrorText = view.findViewById(R.id.text_error_transfer);
8989
storageWarningText = view.findViewById(R.id.text_error_storage);
90-
progressBar = view.findViewById(R.id.progressBar);
90+
progressBar = view.findViewById(R.id.barRam);
9191
progressDescriptionText = view.findViewById(R.id.progress_description);
9292
pauseButton = view.findViewById(R.id.pauseButton);
9393
pauseButton.setTag("iconCancel");
@@ -205,7 +205,7 @@ public void onClick(View v) {
205205
public void onClick(View v) {
206206
if(pauseButton.getTag().equals("iconCancel")){
207207
//we pause the download
208-
boolean success = downloader.stopAllDownloads();
208+
boolean success = downloader.pauseAllDownloads();
209209
if(success) {
210210
//we change the icon and tag
211211
pauseButton.setImageResource(R.drawable.play_icon);
@@ -242,9 +242,6 @@ public void onStart() {
242242
final DownloadManager.Callback callback = new DownloadManager.Callback() {
243243
public void onServiceConnected(){
244244
ArrayList<DownloadGroupInfo> downloadStatus = downloader.getDownloadsStatus();
245-
// we eventually start the download if it is the first time
246-
DownloadGroupInfo downloadGroupInfo = new DownloadGroupInfo(DOWNLOAD_INFOS);
247-
if(downloadStatus == null || !downloadStatus.contains(downloadGroupInfo)) downloader.startDownload(downloadGroupInfo);
248245
// we change the GUI based on current download status
249246
if(downloadStatus != null){
250247
int index = downloadStatus.indexOf(DOWNLOAD_INFOS);
@@ -306,6 +303,11 @@ public void onError(DownloadGroupInfo downloadGroup, DownloadInfo download, int
306303
};
307304

308305
downloader.subscribeAndResumeDownload(callback);
306+
ArrayList<DownloadGroupInfo> downloadStatus = downloader.getSavedDownloadStatus();
307+
// we eventually start the download if it is the first time
308+
DownloadGroupInfo downloadGroupInfo = new DownloadGroupInfo(DOWNLOAD_INFOS);
309+
if(downloadStatus == null || !downloadStatus.contains(downloadGroupInfo)) downloader.startDownload(downloadGroupInfo);
310+
309311
}
310312
}
311313

app/src/main/java/nie/translator/rtranslator/downloader2/DownloadGroupInfo.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
import nie.translator.rtranslator.bluetooth.Peer;
1515

1616
public class DownloadGroupInfo implements Parcelable{
17-
public DownloadInfoExtended[] downloadsInfo;
17+
@NonNull
18+
public final DownloadInfoExtended[] downloadsInfo;
1819
public int runningDownloadIndex = -1;
1920
private int currentProgress = -1;
2021
private boolean allDownloadCompleted = false;

app/src/main/java/nie/translator/rtranslator/downloader2/DownloadManager.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public void onError(DownloadGroupInfo downloadGroup, DownloadInfo download, int
6767
public void subscribeAndResumeDownload(@Nullable Callback callback) {
6868
if(this.callback == null) {
6969
this.callback = callback;
70-
boolean shouldStartService = areDownloadsRunning(false);
70+
boolean shouldStartService = areDownloadsRunning(true);
7171
if(shouldStartService) {
7272
startAndBindService();
7373
}
@@ -79,7 +79,10 @@ public void unsubscribe() {
7979
if (downloaderService != null) {
8080
downloaderService.unregisterClient(serviceCallback);
8181
}
82-
context.unbindService(this);
82+
boolean shouldStopService = !areDownloadsRunning(false);
83+
if(shouldStopService) {
84+
stopAndUnbindService();
85+
}
8386
this.callback = null;
8487
}
8588
}
@@ -95,7 +98,7 @@ public void startDownload(DownloadGroupInfo downloadGroup){
9598
}
9699
}
97100

98-
public boolean stopDownload(DownloadGroupInfo downloadGroup){
101+
public boolean pauseDownload(DownloadGroupInfo downloadGroup){
99102
if(downloaderService != null) {
100103
downloaderService.pauseDownload(downloadGroup);
101104
return true;
@@ -124,7 +127,7 @@ public boolean startAllDownloads() {
124127
return false;
125128
}
126129

127-
public boolean stopAllDownloads() {
130+
public boolean pauseAllDownloads() {
128131
if(downloaderService != null) {
129132
downloaderService.pauseAllDownloads();
130133
return true;
@@ -156,6 +159,14 @@ private void startAndBindService(){
156159
Log.d("bind download", result ? "success" : "failed");
157160
}
158161

162+
private void stopAndUnbindService(){
163+
//we unbind from the service
164+
context.unbindService(this);
165+
// stop the service
166+
final Intent intent = new Intent(context, DownloaderService.class);
167+
context.stopService(intent);
168+
}
169+
159170
private boolean areDownloadsRunning(boolean includePaused){
160171
SharedPreferences sharedPreferences = context.getSharedPreferences("default", Context.MODE_PRIVATE);
161172
String downloadsStatusString = sharedPreferences.getString("downloadsStatus", "");
@@ -174,6 +185,17 @@ private boolean areDownloadsRunning(boolean includePaused){
174185
return false;
175186
}
176187

188+
public ArrayList<DownloadGroupInfo> getSavedDownloadStatus(){
189+
SharedPreferences sharedPreferences = context.getSharedPreferences("default", Context.MODE_PRIVATE);
190+
String downloadsStatusString = sharedPreferences.getString("downloadsStatus", "");
191+
if (!downloadsStatusString.isEmpty()) {
192+
//we check if there are unfinished downloads that are not paused (or also paused ones if includePaused is true)
193+
Gson gson = new Gson();
194+
return gson.fromJson(downloadsStatusString, new TypeToken<ArrayList<DownloadGroupInfo>>() {}.getType());
195+
}
196+
return new ArrayList<>();
197+
}
198+
177199
@Override
178200
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
179201
this.downloaderService = ((DownloaderService.LocalBinder) iBinder).getService();

app/src/main/java/nie/translator/rtranslator/downloader2/Downloader2.java

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import com.downloader.OnStartOrResumeListener;
1414
import com.downloader.PRDownloader;
1515
import com.downloader.Progress;
16+
import com.downloader.Status;
1617

1718
import java.io.BufferedInputStream;
1819
import java.io.File;
@@ -35,7 +36,6 @@ public class Downloader2 {
3536
private final DownloadGroupInfo downloadGroupInfo;
3637
private ClientCallback callback;
3738
private int lastDownloadSuccessIndex = -1;
38-
private boolean allCompleted = false;
3939

4040
public Downloader2(DownloadGroupInfo downloadGroupInfo, Context context, ClientCallback callback) {
4141
this.downloadGroupInfo = downloadGroupInfo;
@@ -76,8 +76,7 @@ public void startDownloads(){
7676
public void pauseDownloads(){
7777
int currentDownloadIndex = downloadGroupInfo.getRunningDownloadIndex();
7878
if(currentDownloadIndex != -1) {
79-
// we cancel the current download (for now this is the best option, it is difficult, if not impossible, to pause without having access to the server)
80-
PRDownloader.cancel(downloadGroupInfo.downloadsInfo[currentDownloadIndex].getDownloadId());
79+
PRDownloader.pause(downloadGroupInfo.downloadsInfo[currentDownloadIndex].getDownloadId());
8180
downloadGroupInfo.setRunningDownloadIndex(-1);
8281
}
8382
}
@@ -89,7 +88,7 @@ public void cancelDownloads(){
8988
PRDownloader.cancel(downloadGroupInfo.downloadsInfo[currentDownloadIndex].getDownloadId());
9089
}
9190
// we delete the already downloaded files of this group of download
92-
for (int i = 0; i <= downloadGroupInfo.downloadsInfo.length; i++){
91+
for (int i = 0; i < downloadGroupInfo.downloadsInfo.length; i++){
9392
File file = new File(downloadGroupInfo.downloadsInfo[i].getDestinationCompletePath());
9493
if (file.exists()) {
9594
file.delete();
@@ -104,7 +103,15 @@ public DownloadGroupInfo getDownloadGroupInfo() {
104103

105104
private void startDownload(int index){
106105
downloadGroupInfo.setRunningDownloadIndex(index);
107-
int downloadId = PRDownloader.download(downloadGroupInfo.downloadsInfo[index].getUrl(), downloadGroupInfo.downloadsInfo[index].getDestinationPath(), downloadGroupInfo.downloadsInfo[index].getName())
106+
int downloadId = downloadGroupInfo.downloadsInfo[index].getDownloadId();
107+
if(downloadId != -1){
108+
if(PRDownloader.getStatus(downloadId) == Status.PAUSED){
109+
PRDownloader.resume(downloadId); //resume if the download was paused during this lifetime of the app
110+
return;
111+
}
112+
}
113+
//start the download from scratch or resume it after the app has been restarted
114+
downloadId = PRDownloader.download(downloadGroupInfo.downloadsInfo[index].getUrl(), downloadGroupInfo.downloadsInfo[index].getDestinationPath(), downloadGroupInfo.downloadsInfo[index].getName())
108115
.build()
109116
.setOnStartOrResumeListener(new OnStartOrResumeListener() {
110117
@Override
@@ -134,8 +141,8 @@ public void onProgress(Progress progress) {
134141
downloadGroupInfo.setCurrentProgress(percentageTotalProgress);
135142
if(runningDownloadIndex >= 0) {
136143
downloadGroupInfo.downloadsInfo[runningDownloadIndex].setCurrentProgress(percentageProgress);
144+
callback.onProgress(downloadGroupInfo, downloadGroupInfo.downloadsInfo[runningDownloadIndex], percentageTotalProgress, percentageProgress, false, false);
137145
}
138-
callback.onProgress(downloadGroupInfo, downloadGroupInfo.downloadsInfo[runningDownloadIndex], percentageTotalProgress, percentageProgress, false, false);
139146
}
140147
})
141148
.start(new OnDownloadListener() {
@@ -226,7 +233,7 @@ private void startNextDownload(){
226233
startDownload(runningDownloadIndex+1);
227234
} else {
228235
//we notify the end of all downloads
229-
allCompleted = true;
236+
downloadGroupInfo.setAllDownloadCompleted(true);
230237
callback.onAllCompleted(downloadGroupInfo);
231238
}
232239
}
@@ -267,7 +274,7 @@ public boolean equals(@Nullable Object obj) {
267274
return super.equals(obj);
268275
}
269276

270-
private int findFirstIncompletedDownload(){
277+
public int findFirstIncompletedDownload(){
271278
int index = 0;
272279
for(int i=0; i<downloadGroupInfo.downloadsInfo.length; i++){
273280
if(downloadGroupInfo.downloadsInfo[i].isAllCompleted()){

0 commit comments

Comments
 (0)