Handling Multiple Downloads With Notifications Using Retrofit Library - android

I'm following a tutorial to download files using the Retrofit library.
My app's UI has several different buttons which download different files using the above method. The problem is when someone presses another button after pressing the first, it's queued and starts after the first finishes. I want it to start right away simultaneously.
Here's the code for the DownloadService:
public class DownloadService extends IntentService {
public DownloadService() {
super("Download Service");
}
private int totalFileSize;
private NotificationCompat.Builder notificationBuilder;
private NotificationManager notificationManager;
#Override
protected void onHandleIntent(Intent intent) {
MyApp x = (MyApp)getApplicationContext();
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_file_download_deep_orange_a400_18dp)
.setContentTitle("Downloading")
.setContentText("Please wait...")
.setAutoCancel(true);
notificationManager.notify(x.ID, notificationBuilder.build());
Log.i("Paras", "onHandleIntent: " + x.filename + x.url);
initDownload(x.filename,x.url,x.ID);
}
private void initDownload(String filename, String url, int id) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://dl.dropboxusercontent.com/")
.build();
RequestInterface.RetrofitInterface retrofitInterface = retrofit.create(RequestInterface.RetrofitInterface.class);
Call<ResponseBody> request = retrofitInterface.downloadFile(url);
try {
downloadFile(request.execute().body(),filename,id);
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
private void downloadFile(ResponseBody body, String filename,int id) throws IOException {
int count;
byte data[] = new byte[1024 * 4];
long fileSize = body.contentLength();
InputStream bis = new BufferedInputStream(body.byteStream(), 1024 * 8);
File outputFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), filename);
OutputStream output = new FileOutputStream(outputFile);
long total = 0;
long startTime = System.currentTimeMillis();
int timeCount = 1;
while ((count = bis.read(data)) != -1) {
total += count;
totalFileSize = (int) (fileSize / (Math.pow(1, 2))) / 1000;
double current = Math.round(total / (Math.pow(1, 2))) / 1000;
int progress = (int) ((total * 100) / fileSize);
long currentTime = System.currentTimeMillis() - startTime;
Download download = new Download();
download.setTotalFileSize(totalFileSize);
if (currentTime > 1000 * timeCount) {
download.setCurrentFileSize((int) current);
download.setProgress(progress);
sendNotification(download,id);
timeCount++;
}
output.write(data, 0, count);
}
onDownloadComplete(filename,id);
output.flush();
output.close();
bis.close();
}
private void sendNotification(Download download, int id) {
sendIntent(download);
notificationBuilder.setProgress(100, download.getProgress(), false);
notificationBuilder.setContentText("Downloading file " + download.getCurrentFileSize() + "/" + totalFileSize + " KB");
notificationManager.notify(id, notificationBuilder.build());
}
private void sendIntent(Download download) {
Intent intent = new Intent(subject.MESSAGE_PROGRESS);
intent.putExtra("download", download);
LocalBroadcastManager.getInstance(DownloadService.this).sendBroadcast(intent);
}
private void onDownloadComplete(String filename,int id) {
try {
Download download = new Download();
download.setProgress(100);
sendIntent(download);
notificationManager.cancel(id);
notificationBuilder.setProgress(0, 0, false);
notificationBuilder.setContentText("Tap to open");
notificationManager.notify(id, notificationBuilder.build());
String path1 = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/" + filename;
File file = new File(path1);
Uri uri_path = Uri.fromFile(file);
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension
(MimeTypeMap.getFileExtensionFromUrl(path1));
Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
intent.setType(mimeType);
intent.setDataAndType(uri_path, mimeType);
PendingIntent pIntent = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), intent, 0);
String string = filename;
notificationBuilder
.setContentIntent(pIntent)
.setAutoCancel(true)
.setContentTitle(string + " Downloaded");
Log.i("Paras", "onDownloadComplete: " + string);
notificationManager.notify(id, notificationBuilder.build());
} catch (Exception ex) {
}
}
#Override
public void onTaskRemoved(Intent rootIntent) {
}
}
Then I read about IntentService and Service classes. Do Service classes allow simultaneous downloads? I tried something like this:
public class DownloadService extends Service {
public DownloadService() {
super();
}
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
MyApp x = (MyApp)getApplicationContext();
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationBuilder = new NotificationCompat.Builder(getBaseContext())
.setSmallIcon(R.drawable.ic_file_download_deep_orange_a400_18dp)
.setContentTitle("Downloading")
.setContentText("Please wait...")
.setAutoCancel(true);
notificationManager.notify(x.ID, notificationBuilder.build());
Log.i("Paras", "onHandleIntent: " + x.filename + x.url);
initDownload(x.filename,x.url,x.ID);
}
}
#Override
public void onCreate() {
// Start up the thread running the service. Note that we create a
// separate thread because the service normally runs in the process's
// main thread, which we don't want to block. We also make it
// background priority so CPU-intensive work will not disrupt our UI.
HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the job
MyApp x = (MyApp)getApplicationContext();
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj= intent.putExtra("ID",x.ID);
mServiceHandler.sendMessage(msg);
// If we get killed, after returning from here, restart
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private int totalFileSize;
private NotificationCompat.Builder notificationBuilder;
private NotificationManager notificationManager;
private void initDownload(String filename, String url, int id) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://dl.dropboxusercontent.com/")
.build();
RequestInterface.RetrofitInterface retrofitInterface = retrofit.create(RequestInterface.RetrofitInterface.class);
Call<ResponseBody> request = retrofitInterface.downloadFile(url);
try {
downloadFile(request.execute().body(),filename,id);
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
private void downloadFile(ResponseBody body, String filename,int id) throws IOException {
int count;
byte data[] = new byte[1024 * 4];
long fileSize = body.contentLength();
InputStream bis = new BufferedInputStream(body.byteStream(), 1024 * 8);
File outputFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), filename);
OutputStream output = new FileOutputStream(outputFile);
long total = 0;
long startTime = System.currentTimeMillis();
int timeCount = 1;
while ((count = bis.read(data)) != -1) {
total += count;
totalFileSize = (int) (fileSize / (Math.pow(1, 2))) / 1000;
double current = Math.round(total / (Math.pow(1, 2))) / 1000;
int progress = (int) ((total * 100) / fileSize);
long currentTime = System.currentTimeMillis() - startTime;
Download download = new Download();
download.setTotalFileSize(totalFileSize);
if (currentTime > 1000 * timeCount) {
download.setCurrentFileSize((int) current);
download.setProgress(progress);
sendNotification(download,id);
timeCount++;
}
output.write(data, 0, count);
}
onDownloadComplete(filename,id);
output.flush();
output.close();
bis.close();
}
private void sendNotification(Download download, int id) {
sendIntent(download);
notificationBuilder.setProgress(100, download.getProgress(), false);
notificationBuilder.setContentText("Downloading file " + download.getCurrentFileSize() + "/" + totalFileSize + " KB");
notificationManager.notify(id, notificationBuilder.build());
}
private void sendIntent(Download download) {
Intent intent = new Intent(subject.MESSAGE_PROGRESS);
intent.putExtra("download", download);
LocalBroadcastManager.getInstance(DownloadService.this).sendBroadcast(intent);
}
private void onDownloadComplete(String filename,int id) {
try {
Download download = new Download();
download.setProgress(100);
sendIntent(download);
notificationManager.cancel(id);
notificationBuilder.setProgress(0, 0, false);
notificationBuilder.setContentText("Tap to open");
notificationManager.notify(id, notificationBuilder.build());
String path1 = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/" + filename;
File file = new File(path1);
Uri uri_path = Uri.fromFile(file);
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension
(MimeTypeMap.getFileExtensionFromUrl(path1));
Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
intent.setType(mimeType);
intent.setDataAndType(uri_path, mimeType);
PendingIntent pIntent = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), intent, 0);
String string = filename;
notificationBuilder
.setContentIntent(pIntent)
.setAutoCancel(true)
.setContentTitle(string + " Downloaded");
Log.i("Paras", "onDownloadComplete: " + string);
notificationManager.notify(id, notificationBuilder.build());
} catch (Exception ex) {
}
}
#Override
public void onTaskRemoved(Intent rootIntent) {
}
}
But it didn't work. Any clues what I should do? I'm ready to give more details if required.
Edit 1: DownloadService runs on a function "startDownload" which is executed by various buttons. As you can see in 2nd code, class Extends Service. There is one thread which handles all those button clicks. If you look in comments, it's suggested that I should use Service and different threads for all those clicks. Now how can I make so many threads programmatically. There are almost 40 buttons which make use of DownloadService.

Thanks to #Lxu, I have got it working. So IntentServiceis meant to do one task at a time and can't do multiple tasks simultaneously. We should use Serviceinstead. It allows multiple tasks to be performed simultaneously. We can create multiple threads inside the Service which will be executed simultaneously. My problem got solved by putting all the code of onCreate() to onStartCommand(). When a service is called for the first time, onCreate() is called and after that, it's not called anymore no matter how many times service is called. On every service call, onStartCommand() is executed which creates new thread every time. That's it.
Here's the complete code:
public class DownloadService extends Service {
public DownloadService() {
super();
}
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
int id1;
int id2;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
MyApp x = (MyApp)getApplicationContext();
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationBuilder = new NotificationCompat.Builder(getApplicationContext())
.setSmallIcon(R.drawable.ic_file_download_deep_orange_a400_18dp)
.setContentTitle("Downloading")
.setContentText("Please wait...")
.setAutoCancel(true);
notificationManager.notify(x.ID, notificationBuilder.build());
Log.i("Paras", "onHandleIntent: " + x.filename + x.url + " " + x.ID);
initDownload(x.filename,x.url,x.ID);
}
}
#Override
public void onCreate() {
// Get the HandlerThread's Looper and use it for our Handler
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the job
HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
MyApp x = (MyApp)getApplicationContext();
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
// If we get killed, after returning from here, restart
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private int totalFileSize;
private NotificationCompat.Builder notificationBuilder;
private NotificationManager notificationManager;
private void initDownload(String filename, String url, int id) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://dl.dropboxusercontent.com/")
.build();
RequestInterface.RetrofitInterface retrofitInterface = retrofit.create(RequestInterface.RetrofitInterface.class);
Call<ResponseBody> request = retrofitInterface.downloadFile(url);
try {
downloadFile(request.execute().body(),filename,id);
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
private void downloadFile(ResponseBody body, String filename,int id) throws IOException {
int count;
byte data[] = new byte[1024 * 4];
long fileSize = body.contentLength();
InputStream bis = new BufferedInputStream(body.byteStream(), 1024 * 8);
File outputFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), filename);
OutputStream output = new FileOutputStream(outputFile);
long total = 0;
long startTime = System.currentTimeMillis();
int timeCount = 1;
while ((count = bis.read(data)) != -1) {
total += count;
totalFileSize = (int) (fileSize / (Math.pow(1, 2))) / 1000;
double current = Math.round(total / (Math.pow(1, 2))) / 1000;
int progress = (int) ((total * 100) / fileSize);
long currentTime = System.currentTimeMillis() - startTime;
Download download = new Download();
download.setTotalFileSize(totalFileSize);
if (currentTime > 1000 * timeCount) {
download.setCurrentFileSize((int) current);
download.setProgress(progress);
sendNotification(download,id);
timeCount++;
}
output.write(data, 0, count);
}
onDownloadComplete(filename,id);
output.flush();
output.close();
bis.close();
}
private void sendNotification(Download download, int id) {
sendIntent(download,id);
notificationBuilder.setProgress(100, download.getProgress(), false)
.setContentTitle("Downloading");
notificationBuilder.setContentText("Downloading file " + download.getCurrentFileSize() + "/" + totalFileSize + " KB");
notificationManager.notify(id, notificationBuilder.build());
}
private void sendIntent(Download download, int id) {
Intent intent = new Intent(subject.MESSAGE_PROGRESS);
intent.putExtra("download", download);
LocalBroadcastManager.getInstance(DownloadService.this).sendBroadcast(intent);
}
private void onDownloadComplete(String filename,int id) {
try {
Download download = new Download();
download.setProgress(100);
sendIntent(download,id);
notificationManager.cancel(id);
notificationBuilder.setProgress(0, 0, false);
notificationBuilder.setContentText("Tap to open");
notificationManager.notify(id, notificationBuilder.build());
String path1 = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/" + filename;
File file = new File(path1);
Uri uri_path = Uri.fromFile(file);
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension
(MimeTypeMap.getFileExtensionFromUrl(path1));
Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
intent.setType(mimeType);
intent.setDataAndType(uri_path, mimeType);
PendingIntent pIntent = PendingIntent.getActivity(this,(int) System.currentTimeMillis(), intent, 0);
String string = filename;
notificationBuilder
.setContentIntent(pIntent)
.setAutoCancel(true)
.setContentTitle(string + " Downloaded");
Log.i("Paras", "onDownloadComplete: " + string);
notificationManager.notify(id, notificationBuilder.build());
}catch (Exception ex){
}
}
#Override
public void onTaskRemoved(Intent rootIntent) {
}
}

Related

New Api AudioPlaybackCaptureConfiguration (android 10) fails to record voice calls

I tried to use new AudioPlaybackCapture method to record some media in an android 10 device.
I managed to record all media sounds such as youtube videos, music etc. But my goal is to check weather we can use this in recording incoming voice calls. I tried to set various values for the usage parameter but with no luck. Always no voice from call is recorded in either case, even with speaker phone on.
I used the following service to record calls. Tried to set
AudioAttributes.USAGE_MEDIA
AudioAttributes.USAGE_VOICE_COMMUNICATION and most other parameters but did not manage to record calls. Other media can be perfectly recorded using this code.
Here's my service, Broadcast massages from an activity is used to invoke start and stop recording functionalities.
public class MediaCaptureService extends Service {
public static final String ACTION_ALL = "ALL";
public static final String ACTION_START = "ACTION_START";
public static final String ACTION_STOP = "ACTION_STOP";
public static final String EXTRA_RESULT_CODE = "EXTRA_RESULT_CODE";
public static final String EXTRA_ACTION_NAME = "ACTION_NAME";
private static final int RECORDER_SAMPLERATE = 8000;
private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_MONO;
private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
NotificationCompat.Builder _notificationBuilder;
NotificationManager _notificationManager;
private String NOTIFICATION_CHANNEL_ID = "ChannelId";
private String NOTIFICATION_CHANNEL_NAME = "Channel";
private String NOTIFICATION_CHANNEL_DESC = "ChannelDescription";
private int NOTIFICATION_ID = 1000;
private static final String ONGING_NOTIFICATION_TICKER = "RecorderApp";
int BufferElements2Rec = 1024; // want to play 2048 (2K) since 2 bytes we use only 1024
int BytesPerElement = 2; // 2 bytes in 16bit format
AudioRecord _recorder;
private boolean _isRecording = false;
private MediaProjectionManager _mediaProjectionManager;
private MediaProjection _mediaProjection;
private Thread _recordingThread = null;
Intent _callingIntent;
public MediaCaptureService() {
}
#Override
public void onCreate() {
super.onCreate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//Call Start foreground with notification
Intent notificationIntent = new Intent(this, MediaCaptureService.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
_notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_foreground))
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("Starting Service")
.setContentText("Starting monitoring service")
.setTicker(ONGING_NOTIFICATION_TICKER)
.setContentIntent(pendingIntent);
Notification notification = _notificationBuilder.build();
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription(NOTIFICATION_CHANNEL_DESC);
_notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
_notificationManager.createNotificationChannel(channel);
startForeground(NOTIFICATION_ID, notification);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
_mediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
}
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
_callingIntent = intent;
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_ALL);
registerReceiver(_actionReceiver, filter);
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void startRecording(Intent intent) {
//final int resultCode = intent.getIntExtra(EXTRA_RESULT_CODE, 0);
_mediaProjection = _mediaProjectionManager.getMediaProjection(-1, intent);
startRecording(_mediaProjection);
}
#TargetApi(29)
private void startRecording(MediaProjection mediaProjection ) {
AudioPlaybackCaptureConfiguration config =
new AudioPlaybackCaptureConfiguration.Builder(mediaProjection)
.addMatchingUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
.build();
AudioFormat audioFormat = new AudioFormat.Builder()
.setEncoding(RECORDER_AUDIO_ENCODING)
.setSampleRate(RECORDER_SAMPLERATE)
.setChannelMask(RECORDER_CHANNELS)
.build();
_recorder = new AudioRecord.Builder()
//.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION)
.setAudioFormat(audioFormat)
.setBufferSizeInBytes(BufferElements2Rec * BytesPerElement)
.setAudioPlaybackCaptureConfig(config)
.build();
_recorder.startRecording();
_recordingThread = new Thread(new Runnable() {
public void run() {
writeAudioDataToFile();
}
}, "AudioRecorder Thread");
_isRecording = true;
_recordingThread.start();
}
private byte[] short2byte(short[] sData) {
int shortArrsize = sData.length;
byte[] bytes = new byte[shortArrsize * 2];
for (int i = 0; i < shortArrsize; i++) {
bytes[i * 2] = (byte) (sData[i] & 0x00FF);
bytes[(i * 2) + 1] = (byte) (sData[i] >> 8);
sData[i] = 0;
}
return bytes;
}
private void writeAudioDataToFile() {
// Write the output audio in byte
Log.i(MainActivity.LOG_PREFIX, "Recording started. Computing output file name");
File sampleDir = new File(getExternalFilesDir(null), "/TestRecordingDasa1");
if (!sampleDir.exists()) {
sampleDir.mkdirs();
}
String fileName = "Record-" + new SimpleDateFormat("dd-MM-yyyy-hh-mm-ss").format(new Date()) + ".pcm";
String filePath = sampleDir.getAbsolutePath() + "/" + fileName;
//String filePath = "/sdcard/voice8K16bitmono.pcm";
short sData[] = new short[BufferElements2Rec];
FileOutputStream os = null;
try {
os = new FileOutputStream(filePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
while (_isRecording) {
// gets the voice output from microphone to byte format
_recorder.read(sData, 0, BufferElements2Rec);
System.out.println("Short wirting to file" + sData.toString());
try {
// // writes the data to file from buffer
// // stores the voice buffer
byte bData[] = short2byte(sData);
os.write(bData, 0, BufferElements2Rec * BytesPerElement);
} catch (IOException e) {
e.printStackTrace();
}
}
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
Log.i(MainActivity.LOG_PREFIX, String.format("Recording finished. File saved to '%s'\nadb pull %s .", filePath, filePath));
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void stopRecording() {
// stops the recording activity
if (null != _recorder) {
_isRecording = false;
_recorder.stop();
_recorder.release();
_recorder = null;
}
_mediaProjection.stop();
stopSelf();
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(_actionReceiver);
}
BroadcastReceiver _actionReceiver = new BroadcastReceiver() {
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equalsIgnoreCase(ACTION_ALL)) {
String actionName = intent.getStringExtra(EXTRA_ACTION_NAME);
if (actionName != null && !actionName.isEmpty()) {
if (actionName.equalsIgnoreCase(ACTION_START)) {
startRecording(_callingIntent);
} else if (actionName.equalsIgnoreCase(ACTION_STOP)){
stopRecording();
}
}
}
}
};
}
This was tested in google pixel device with android 10. Just wanted to know weather this new api can be used in recording calls or media only. Here is the documentation of this new API.
Playback capture.
What would be the possible mistake im doing here?

Android UI freeze when service is downloading progress

I'm using the library bitcoinj to create a Android wallet. The case is that I want the blockchain to be downloaded in the background so that the user can start using the other features of the app, but when it starts the download and opens a new activity, the application freezes, you can't use anything, not even return to the previous screen. This is part of the code:
public class BitcoinService extends Service {
private final PeerDataEventListener blockchainDownloadListener = new AbstractPeerEventListener() {
private final long CALLBACK_TIME = 1000L;
private final AtomicLong lastMessageTime = new AtomicLong(0);
private int height;
private int blocksLeft;
private Block block;
#Override
public void onBlocksDownloaded(final Peer peer, final Block block, final FilteredBlock filteredBlock, final int blocksLeft) {
config.maybeIncrementBestChainHeightEver(blockChain.getChainHead().getHeight());
delayHandler.removeCallbacksAndMessages(null);
final long now = System.currentTimeMillis();
this.block = block;
this.height = (int) peer.getBestHeight() - blocksLeft;
this.blocksLeft = blocksLeft;
if (now - lastMessageTime.get() > CALLBACK_TIME) {
delayHandler.post(RUNNER);
} else {
delayHandler.postDelayed(RUNNER, CALLBACK_TIME);
}
}
private final Runnable RUNNER = new Runnable() {
#Override
public void run() {
notifyBlockchainProgress(height, (height + blocksLeft));
Log.e(TAG, "LAST_BLOCK=" + height + ", REMAINS=" + blocksLeft);
if (blocksLeft == 0) {
broadcastBlockchainDownloaded();
}
}
};
};
private final BroadcastReceiver connectivityReceiver = new BroadcastReceiver() {
#SuppressLint("Wakelock")
#Override
public void onReceive(final Context context, final Intent intent) {
Log.d(TAG, "acquiring wakelock");
wakeLock.acquire();
// consistency check
final int walletLastBlockSeenHeight = wallet.getLastBlockSeenHeight();
final int bestChainHeight = blockChain.getBestChainHeight();
if (walletLastBlockSeenHeight != -1 && walletLastBlockSeenHeight != bestChainHeight) {
final String message = "wallet/blockchain out of sync: " + walletLastBlockSeenHeight + "/" + bestChainHeight;
Log.e(TAG, message);
}
Log.i(TAG, "starting peergroup");
peerGroup = new PeerGroup(Constants.WALLET.NETWORK_PARAMETERS, blockChain);
peerGroup.setDownloadTxDependencies(false);
peerGroup.setUserAgent("TestWallet", "0.0.1");
peerGroup.setMaxConnections(6);
peerGroup.setConnectTimeoutMillis(15000);
peerGroup.setPeerDiscoveryTimeoutMillis(10000);
// start peergroup
peerGroup.startAsync();
peerGroup.startBlockChainDownload(blockchainDownloadListener);
}
};
private final Handler delayHandler = new Handler();
private PeerGroup peerGroup;
private WakeLock wakeLock;
private PeerConnectivityListener peerConnectivityListener;
private NotificationManager nm;
private Configuration config;
private Wallet wallet;
#Override
public void onCreate() {
wallet = new Wallet(Constants.WALLET.NETWORK_PARAMETERS);
nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
final String lockName = getPackageName() + " blockchain sync";
final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, lockName);
config = Configuration.getInstance();
broadcastPeerState(0);
blockChainFile = Constants.WALLET.BLOCKCHAIN_FILE;
final boolean blockChainFileExists = blockChainFile.exists();
if (!blockChainFileExists) {
new File(Constants.WALLET.WALLET_PATH).mkdirs();
}
try {
blockStore = new SPVBlockStore(Constants.WALLET.NETWORK_PARAMETERS, blockChainFile);
blockStore.getChainHead(); // detect corruptions as early as possible
final long earliestKeyCreationTime = wallet.getEarliestKeyCreationTime();
if (!blockChainFileExists && earliestKeyCreationTime > 0){
try {
config.setDeletingBlockchain(true);
final long start = System.currentTimeMillis();
final InputStream checkpointsInputStream = getAssets().open("bitcoin/" + Constants.WALLET.CHECKPOINTS_FILENAME);
CheckpointManager.checkpoint(Constants.WALLET.NETWORK_PARAMETERS, checkpointsInputStream, blockStore, earliestKeyCreationTime);
Log.i(TAG, String.format("checkpoints loaded from '%1$s', took %2$dms", Constants.WALLET.CHECKPOINTS_FILENAME, System.currentTimeMillis() - start));
} catch (final IOException x) {
Log.e(TAG, "problem reading checkpoints, continuing without", x);
}
}
} catch (final BlockStoreException x) {
blockChainFile.delete();
final String msg = "blockstore cannot be created";
Log.e(TAG, msg, x);
}
try {
blockChain = new BlockChain(Constants.WALLET.NETWORK_PARAMETERS, walletHelper.getMainWallet(), blockStore);
} catch (final BlockStoreException x) {
throw new Error("blockchain cannot be created", x);
}
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_LOW);
intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
registerReceiver(connectivityReceiver, intentFilter); // implicitly start PeerGroup
}
#Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
Log.e(TAG, "onStartCommand");
...
return START_NOT_STICKY;
}
private void notifyBlockchainProgress(int progress, int max) {
boolean isCompleted = progress == max;
if (config.isDeletingBlockchain()) {
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
long percent = Math.round(Math.floor((progress * 100) / max));
mBuilder.setContentTitle("Blockchain download")
.setContentText(" Synchronization in progress - " + percent + "%")
.setSmallIcon(R.drawable.ic_logo_splash)
.setProgress(max, progress, false)
.setAutoCancel(false);
if (isCompleted) {
mBuilder.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setProgress(0, 0, false)
.setAutoCancel(true)
.setContentText(getString(R.string.synchronization_completed));
config.setDeletingBlockchain(false);
}
Notification notif = mBuilder.build();
if (isCompleted) {
notif.flags = Notification.FLAG_FOREGROUND_SERVICE;
} else {
notif.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE;
}
nm.notify(2, notif);
}
}
public void broadcastBlockchainDownloaded() {
Intent i = new Intent(UiRefreshReceiver.REFRESH_UI);
LocalBroadcastManager.getInstance(this).sendBroadcast(i);
}
}
I used part of the code of the official project of the Android wallet
Service in android runs in UI thread. You need to put all the job into different thread inside your Service
You need to use IntentService for downloading process.
public class BitcoinService extends IntentService {
private final PeerDataEventListener blockchainDownloadListener = new AbstractPeerEventListener() {
private final long CALLBACK_TIME = 1000L;
private final AtomicLong lastMessageTime = new AtomicLong(0);
private int height;
private int blocksLeft;
private Block block;
#Override
public void onBlocksDownloaded(final Peer peer, final Block block, final FilteredBlock filteredBlock, final int blocksLeft) {
config.maybeIncrementBestChainHeightEver(blockChain.getChainHead().getHeight());
delayHandler.removeCallbacksAndMessages(null);
final long now = System.currentTimeMillis();
this.block = block;
this.height = (int) peer.getBestHeight() - blocksLeft;
this.blocksLeft = blocksLeft;
if (now - lastMessageTime.get() > CALLBACK_TIME) {
delayHandler.post(RUNNER);
} else {
delayHandler.postDelayed(RUNNER, CALLBACK_TIME);
}
}
private final Runnable RUNNER = new Runnable() {
#Override
public void run() {
notifyBlockchainProgress(height, (height + blocksLeft));
Log.e(TAG, "LAST_BLOCK=" + height + ", REMAINS=" + blocksLeft);
if (blocksLeft == 0) {
broadcastBlockchainDownloaded();
}
}
};
};
private final BroadcastReceiver connectivityReceiver = new BroadcastReceiver() {
#SuppressLint("Wakelock")
#Override
public void onReceive(final Context context, final Intent intent) {
Log.d(TAG, "acquiring wakelock");
wakeLock.acquire();
// consistency check
final int walletLastBlockSeenHeight = wallet.getLastBlockSeenHeight();
final int bestChainHeight = blockChain.getBestChainHeight();
if (walletLastBlockSeenHeight != -1 && walletLastBlockSeenHeight != bestChainHeight) {
final String message = "wallet/blockchain out of sync: " + walletLastBlockSeenHeight + "/" + bestChainHeight;
Log.e(TAG, message);
}
Log.i(TAG, "starting peergroup");
peerGroup = new PeerGroup(Constants.WALLET.NETWORK_PARAMETERS, blockChain);
peerGroup.setDownloadTxDependencies(false);
peerGroup.setUserAgent("TestWallet", "0.0.1");
peerGroup.setMaxConnections(6);
peerGroup.setConnectTimeoutMillis(15000);
peerGroup.setPeerDiscoveryTimeoutMillis(10000);
// start peergroup
peerGroup.startAsync();
peerGroup.startBlockChainDownload(blockchainDownloadListener);
}
};
private final Handler delayHandler = new Handler();
private PeerGroup peerGroup;
private WakeLock wakeLock;
private PeerConnectivityListener peerConnectivityListener;
private NotificationManager nm;
private Configuration config;
private Wallet wallet;
#Override
protected void onHandleIntent(Intent intent) {
wallet = new Wallet(Constants.WALLET.NETWORK_PARAMETERS);
nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
final String lockName = getPackageName() + " blockchain sync";
final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, lockName);
config = Configuration.getInstance();
broadcastPeerState(0);
blockChainFile = Constants.WALLET.BLOCKCHAIN_FILE;
final boolean blockChainFileExists = blockChainFile.exists();
if (!blockChainFileExists) {
new File(Constants.WALLET.WALLET_PATH).mkdirs();
}
try {
blockStore = new SPVBlockStore(Constants.WALLET.NETWORK_PARAMETERS, blockChainFile);
blockStore.getChainHead(); // detect corruptions as early as possible
final long earliestKeyCreationTime = wallet.getEarliestKeyCreationTime();
if (!blockChainFileExists && earliestKeyCreationTime > 0){
try {
config.setDeletingBlockchain(true);
final long start = System.currentTimeMillis();
final InputStream checkpointsInputStream = getAssets().open("bitcoin/" + Constants.WALLET.CHECKPOINTS_FILENAME);
CheckpointManager.checkpoint(Constants.WALLET.NETWORK_PARAMETERS, checkpointsInputStream, blockStore, earliestKeyCreationTime);
Log.i(TAG, String.format("checkpoints loaded from '%1$s', took %2$dms", Constants.WALLET.CHECKPOINTS_FILENAME, System.currentTimeMillis() - start));
} catch (final IOException x) {
Log.e(TAG, "problem reading checkpoints, continuing without", x);
}
}
} catch (final BlockStoreException x) {
blockChainFile.delete();
final String msg = "blockstore cannot be created";
Log.e(TAG, msg, x);
}
try {
blockChain = new BlockChain(Constants.WALLET.NETWORK_PARAMETERS, walletHelper.getMainWallet(), blockStore);
} catch (final BlockStoreException x) {
throw new Error("blockchain cannot be created", x);
}
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_LOW);
intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
registerReceiver(connectivityReceiver, intentFilter); // implicitly start PeerGroup
}
private void notifyBlockchainProgress(int progress, int max) {
boolean isCompleted = progress == max;
if (config.isDeletingBlockchain()) {
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
long percent = Math.round(Math.floor((progress * 100) / max));
mBuilder.setContentTitle("Blockchain download")
.setContentText(" Synchronization in progress - " + percent + "%")
.setSmallIcon(R.drawable.ic_logo_splash)
.setProgress(max, progress, false)
.setAutoCancel(false);
if (isCompleted) {
mBuilder.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setProgress(0, 0, false)
.setAutoCancel(true)
.setContentText(getString(R.string.synchronization_completed));
config.setDeletingBlockchain(false);
}
Notification notif = mBuilder.build();
if (isCompleted) {
notif.flags = Notification.FLAG_FOREGROUND_SERVICE;
} else {
notif.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE;
}
nm.notify(2, notif);
}
}
}
Hope this will help you.

How to perform multiple download operations from a single Intent Service with progress update of each operation

I have written code for downloading images through Intent Service
public class UIIntentService extends IntentService {
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
*/
public UIIntentService() {
super("UIIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
downLoadManager();
}
private void downLoadManager() {
// Starting download manager
final DownloadManager manager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(
Uri.parse("http://some_url/xyz.jpg"));
MainActivity.enqueue = manager.enqueue(request);
scheduleAlarm(MainActivity.enqueue);
}
public void scheduleAlarm(long id) {
Intent intent = new Intent(getBaseContext(), com.example.com.downloaddemo.DisplayInoker.class);
intent.putExtra("ID", ""+id);
final PendingIntent pIntent = PendingIntent.getBroadcast(getBaseContext(), com.example.com.downloaddemo.DisplayInoker.REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
long firstMillis = System.currentTimeMillis(); // alarm is set right away
AlarmManager alarm = (AlarmManager) getBaseContext().getSystemService(Context.ALARM_SERVICE);
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, firstMillis,
3000, pIntent);
}
}
My BroadcastReceiver for AlarmManager
public class DisplayInoker extends BroadcastReceiver{
public static final int REQUEST_CODE = 12345;
public static final String ACTION = "DISPLAYRESULT";
private long enqueue;
// Triggered by the Alarm periodically
#Override
public void onReceive(Context context, Intent intent) {
EventBus bus = EventBus.getDefault();
if(intent.getExtras().getString("ID") != null) {
enqueue = Long.parseLong("" + intent.getExtras().getString("ID"));
Log.d("Innnnnnnnnnnnnnnnnnnnnn", ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
final DownloadManager manager = (DownloadManager) context.getSystemService(context.DOWNLOAD_SERVICE);
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(enqueue);
Cursor cursor = manager.query(q);
cursor.moveToFirst();
double bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
double bytes_downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
double percentComplete = 0;
// checking whether file downloaded or not
boolean downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
== DownloadManager.STATUS_SUCCESSFUL ? true : false;
cursor.close();
boolean stopDisplaying = false;
if (!downloaded) {
try {
percentComplete = (bytes_downloaded / bytes_total) * 100;
bus.post("" + (int) percentComplete);
} catch (Exception e) {
percentComplete = 0;
e.printStackTrace();
}
} else {
Log.d("completed", "////////////////////// end ///////////////////////////" + bytes_total + " " + bytes_downloaded);
percentComplete = (bytes_downloaded / bytes_total) * 100;
bus.post("" + (int) percentComplete);
}
}
}
}
Calling my Intent service simply
Intent intentservice = new Intent(MainActivity.this, UIIntentService.class);
startService(intentservice);
This code is working fine and I am receiving progress updates of single download operation.
Now, I want to use this IntentService to perform multiple download operations with progress update of each operation. can you please check whether is it possible through this code or provide some other alternative solution.
Thanks in advance.
Using Handler you can achieve the result.
Please see here.

Download Manager failed the download

I am using DownloadManager to download the following url:
http://dj-videos.us/Music/XclusiveSinGleTrack/320%20Kbps/November%202013/Yo%20Yo%20Honey%20Singh%20-%20Blue%20Eyes-[DJKANG.Com].mp3
But the downloading is failed. I even hit the url on browser and it works properly. Is it the problem of url parsing?
Code: DDownloadService.java
public class DDownloadService extends Service {
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
Context conte;
// NotificationManager notificationManager;
// NotificationCompat.Builder mBuilder;
boolean playing = false;
Runnable runnable;
SharedPreferences pre;
static int countOfCurrent = 0;
String downloadName, downloadUrl;
NotificationManager notificationManager;
NotificationCompat.Builder mBuilder;
// ..
static int downloadNumber = 0;
DownloadManager mgr[] = new DownloadManager[100];
long downloadIds[] = new long[100];
BroadcastReceiver cancelDownload;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
try {
Thread.sleep(5000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
downloadNumber++;
downloadName = pre.getString("downloadname", "");
downloadName = viewSD(downloadName);
downloadUrl = pre.getString("downloadurl", "");
downloadName = downloadName.toLowerCase();
pre.edit()
.putString(
"songsInDownload",
pre.getString("songsInDownload", "") + "|"
+ downloadName).commit();
pre.edit().putInt(downloadName + "no", +downloadNumber).commit();
mgr[downloadNumber] = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
try {
countOfCurrent++;
downloadIds[downloadNumber] = mgr[downloadNumber]
.enqueue(new DownloadManager.Request(Uri
.parse(downloadUrl))
.setAllowedNetworkTypes(
DownloadManager.Request.NETWORK_WIFI
| DownloadManager.Request.NETWORK_MOBILE)
.setAllowedOverRoaming(false)
.setTitle("Downloading")
.setDescription(downloadName)
.setNotificationVisibility(
DownloadManager.Request.VISIBILITY_HIDDEN)
.setDestinationInExternalPublicDir(
Environment.DIRECTORY_MUSIC,
downloadName)
.setVisibleInDownloadsUi(false));
pre.edit()
.putLong(downloadName + "id",
downloadIds[downloadNumber]).commit();
Timer myTimer = new Timer();
myTimer.schedule(new RegrowCornAnimate(downloadNumber,
downloadName), 0, 10);
} catch (IllegalStateException e) {
Toast.makeText(getBaseContext(), "No storage found!",
Toast.LENGTH_SHORT).show();
e.printStackTrace();
} catch (Exception e) {
Toast.makeText(getBaseContext(), " Something wrong happened!",
Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
}
#Override
public void onCreate() {
conte = this;
pre = getSharedPreferences("download", 0);
downloadName = pre.getString("downloadname", "");
downloadUrl = pre.getString("downloadurl", "");
cancelDownload = new BroadcastReceiver() {
#Override
public void onReceive(Context arg0, Intent arg1) {
try {
mgr[pre.getInt(arg1.getExtras().getString("name") + "no", 0)]
.remove(pre.getLong(
arg1.getExtras().getString("name") + "id",
0));
} catch (Exception e) {
e.printStackTrace();
}
}
};
registerReceiver(cancelDownload, new IntentFilter("cancelIt"));
notificationManager = (NotificationManager) conte
.getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(conte)
.setSmallIcon(R.drawable.icon)
.setContentTitle("Downloading in progress").setContentText("");
startForeground(55, mBuilder.build());
notificationManager.cancel(55);
HandlerThread thread = new HandlerThread("ServiceStartArguments", 0);
// //..................
// notificationManager = (NotificationManager) conte
// .getSystemService(Context.NOTIFICATION_SERVICE);
// mBuilder = new NotificationCompat.Builder(conte);
// RemoteViews remoteViews = new RemoteViews(getPackageName(),
// R.layout.notification_layout);
// try {
// mBuilder.setSmallIcon(R.drawable.icon);
// mBuilder.setAutoCancel(false).setOngoing(true)
// .setContent(remoteViews);
// Uri uri = RingtoneManager
// .getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
// mBuilder.setSound(uri);
// notificationManager.notify(Mp3Constants.NOTIFICATION_NUMBER,
// mBuilder.build());
// } catch (Exception e) {
// e.printStackTrace();
// }
// //...................
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// online = intent.getExtras().getString("online");
// link = intent.getExtras().getString("link");
// name = intent.getExtras().getString("name");
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(cancelDownload);
}
class RegrowCornAnimate extends TimerTask {
private final int serial;
private final String name_of_da;
boolean startFlag = true, errorFlag = true;
RegrowCornAnimate(int serial, String name) {
this.serial = serial;
this.name_of_da = name;
}
public void run() {
// Do stuff
int dl_progress = 0;
try {
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(downloadIds[serial]);
Cursor c = mgr[serial].query(q);
c.moveToFirst();
long bytes_downloaded = c
.getInt(c
.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
long bytes_total = c
.getInt(c
.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
dl_progress = (int) ((bytes_downloaded * 100) / bytes_total);
pre.edit().putInt(name_of_da, dl_progress).commit();
switch (c.getInt(c
.getColumnIndex(DownloadManager.COLUMN_STATUS))) {
case DownloadManager.STATUS_FAILED:
// msg = "Download failed!";
// Toast.makeText(getBaseContext(), "Url Broken!",
// Toast.LENGTH_SHORT).show();
sendNotification(1, serial, name_of_da, dl_progress);
this.cancel();
countOfCurrent--;
if (countOfCurrent == 0)
stopSelf();
break;
case DownloadManager.STATUS_PAUSED:
// msg = "Download paused!";
if (errorFlag) {
errorFlag = false;
sendNotification(7, serial, name_of_da, dl_progress);
}
break;
case DownloadManager.STATUS_PENDING:
// msg = "Download pending!";
sendNotification(0, serial, name_of_da, dl_progress);
break;
case DownloadManager.STATUS_RUNNING:
// msg = "Download in progress!";
errorFlag = true;
if (startFlag) {
if (verifyFromSD(name_of_da)) {
startFlag = false;
sendBroadcast(new Intent("start"));
}
}
sendNotification(0, serial, name_of_da, dl_progress);
break;
case DownloadManager.STATUS_SUCCESSFUL:
// msg = "Download complete!";
pre.edit()
.putString(
"songsInDownload",
pre.getString("songsInDownload", "")
.replace("|" + name_of_da, ""))
.commit();
pre.edit().putInt(name_of_da, 100);
sendNotification(0, serial, name_of_da, dl_progress);
this.cancel();
countOfCurrent--;
if (countOfCurrent == 0)
stopSelf();
break;
default:
// msg = "Download is nowhere in sight";
sendNotification(10, serial, name_of_da, dl_progress);
this.cancel();
countOfCurrent--;
if (countOfCurrent == 0)
stopSelf();
break;
}
c.close();
} catch (Exception e) {
e.printStackTrace();
sendNotification(7, serial, name_of_da, dl_progress);
cancel();
countOfCurrent--;
if (countOfCurrent == 0)
stopSelf();
}
}
}
public void sendNotification(int tmout, int nin, String name, int progress) {
if (tmout == 0) {
// notificationManager.notify(nin, mBuilder.build());
if (progress >= 100) {
// notificationManager.cancel(nin);
mBuilder.setSmallIcon(R.drawable.icon)
.setContentTitle("Completed").setContentText(name)
.setAutoCancel(true).setOngoing(false)
.setProgress(100, 100, false);
Uri ttt = Uri.parse(Environment.getExternalStorageDirectory()
.toString() + "/Music/" + name);
pre.edit().putInt("retry", 1).commit();
Intent inten = new Intent(Intent.ACTION_VIEW, ttt);
String arr[] = name.split("\\.");
inten.setDataAndType(ttt, "audio/" + arr[arr.length - 1]);
PendingIntent i = PendingIntent.getActivity(getBaseContext(),
0, inten, 0);
mBuilder.setContentIntent(i);
notificationManager.notify(nin, mBuilder.build());
} else {
mBuilder.setContentTitle("Downloading: " + name)
.setContentText(progress + " %")
.setSmallIcon(R.drawable.icon).setAutoCancel(false)
.setOngoing(true);
mBuilder.setProgress(100, progress, false);
notificationManager.notify(nin, mBuilder.build());
}
} else {
if (tmout == 1) {
mBuilder.setSmallIcon(R.drawable.icon)
.setContentTitle("Failed: " + name)
.setContentText(progress + " %").setAutoCancel(true)
.setProgress(100, progress, false).setOngoing(false);
// Intent intnt = new Intent(Mp3Constants.NOTIFICATION);
// intnt.putExtra("resume", "1");
// intnt.putExtra("url", urlD);
// intnt.putExtra("name", name);
// intnt.putExtra("nin", nin);
// PendingIntent i = PendingIntent
// .getBroadcast(conte, 0, intnt, 0);
// mBuilder.setContentIntent(i);
} else if (tmout == 7) {
mBuilder.setSmallIcon(R.drawable.icon)
.setContentTitle("Cancelled: " + name)
.setAutoCancel(true).setProgress(100, progress, false)
.setOngoing(false);
// Intent intnt = new Intent(Mp3Constants.NOTIFICATION);
// intnt.putExtra("resume", "1");
// intnt.putExtra("url", urlD);
// intnt.putExtra("name", name);
// intnt.putExtra("nin", nin);
// PendingIntent i = PendingIntent
// .getBroadcast(conte, 0, intnt, 0);
// mBuilder.setContentIntent(i);
} else {
mBuilder.setSmallIcon(R.drawable.icon)
.setContentTitle("Interrupted: " + name)
.setContentText("No storage found").setAutoCancel(true)
.setOngoing(false);
}
notificationManager.notify(nin, mBuilder.build());
}
}
private String viewSD(String naame) {
File f = new File(Environment.getExternalStorageDirectory().toString()
+ "/Music");
File[] files = f.listFiles();
if (files == null) {
return naame;
}
while (true) {
String newName = naame;
naame = relooper(files, newName);
if (newName.equals(naame))
break;
}
return naame;
}
public String relooper(File[] files, String name) {
int send = files.length;
for (int i = 0; i < send; i++) {
File file = files[i];
String myfile = file
.getPath()
.substring(file.getPath().lastIndexOf("/") + 1,
file.getPath().length()).toLowerCase();
if (name.equalsIgnoreCase(myfile))
return "copy_of_" + name;
}
return name;
}
private boolean verifyFromSD(String naame) {
File f = new File(Environment.getExternalStorageDirectory().toString()
+ "/Music");
File[] files = f.listFiles();
if (files == null) {
return false;
}
int send = files.length;
for (int i = 0; i < send; i++) {
File file = files[i];
String myfile = file
.getPath()
.substring(file.getPath().lastIndexOf("/") + 1,
file.getPath().length()).toLowerCase();
if (naame.equalsIgnoreCase(myfile))
return true;
}
return false;
}
}
EDIT: I found the problem from logcat:
01-07 11:47:37.313: W/DownloadManager(18893): Exception for id 285: Illegal character in path at index 115: http://dj-videos.us/Music/XclusiveSinGleTrack/320%20Kbps/November%202013/Yo%20Yo%20Honey%20Singh%20-%20Blue%20Eyes-[DJKANG.Com].mp3
01-07 11:47:37.313: W/DownloadManager(18893): java.lang.IllegalArgumentException: Illegal character in path at index 115: http://dj-videos.us/Music/XclusiveSinGleTrack/320%20Kbps/November%202013/Yo%20Yo%20Honey%20Singh%20-%20Blue%20Eyes-[DJKANG.Com].mp3
01-07 11:47:37.313: W/DownloadManager(18893): at java.net.URI.create(URI.java:727)
01-07 11:47:37.313: W/DownloadManager(18893): at android.net.Proxy.getProxy(Proxy.java:113)
01-07 11:47:37.313: W/DownloadManager(18893): at android.net.Proxy.getPreferredHttpHost(Proxy.java:218)
01-07 11:47:37.313: W/DownloadManager(18893): at com.android.providers.downloads.DownloadThread.run(DownloadThread.java:174)
But I still need to know which format to use to parse url for DownloadManager.
The IllegalArgumentException occurs when the URL contains illegal characters such as [ ]. As mentioned in the comments, you need to encode such characters using URLEncoder.
I implemented it this way in my code -
private String checkUrl(String url) {
if(url.contains("[")) {
String[] a = url.split("\\[");
String b = "[" + a[1]; //contains text after [ e.g. [DJKANG.Com].mp3
url = a[0] + URLEncoder.encode(b, "UTF-8"); // encodes illegal characters
}
return url;
}

How to Show download progress in progress bar in Android?

I am using .net web services and I am able to download the file in sd card, But I want to show progress bar when particular file start download and complete and then I want to show options like view and cancel.
Click event Class:
public void onItemClick(AdapterView<?> parent, View v, int position, long id)
{
LazyAdapter ca = (LazyAdapter)parent.getAdapter();
FolderList item_name = (FolderList)ca.getItem(position);
FolderList DocumentID = (FolderList)ca.getItem(position);
FolderList type = (FolderList)ca.getItem(position);
Intent mIntent = new Intent();
mIntent.putExtra("item_name", item_name.folder_name);
mIntent.putExtra("item_id", DocumentID.ID);
mIntent.putExtra("item_type", type.type);
mIntent.getStringExtra("item_name");
String Type = mIntent.getStringExtra("item_type");
Log.i("Type", Type);
if {
// Some code here...
} else {
Intent i = new Intent(getApplicationContext(), Display_image.class);
i.putExtra("item_name", item_name.folder_name);
i.putExtra("ID", DocumentID.ID);
i.putExtra("item_type", type.type);
i.putExtra("User_ID",User_ID);
i.getStringExtra("item_name");
Id = i.getStringExtra("ID");
i.getStringExtra("item_type");
startActivity(i);
}
}
My Code: I want to use download manager
SoapPrimitive DocumentResponse = (SoapPrimitive)Envelope.getResponse();
Log.i("DocumentResponse", DocumentResponse.toString());
String DocAsString = DocumentResponse.toString();
byte[] decodedString = Base64.decode(DocAsString, Base64.DEFAULT);
File direct = new File(Environment.getExternalStorageDirectory() + "/MyFolder");
if(!direct.exists())
{
direct.mkdir();
}
File photo = new File(Environment.getExternalStorageDirectory() + "/MyFolder", Name);
if (photo.exists())
{
photo.delete();
}
try {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(Name));
request.setDescription("Have Fun ;)");
request.setTitle("Downloading...");
// in order for this if to run, you must use the android 3.2 to compile your app
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
}
FileOutputStream fos=new FileOutputStream(photo.getPath());
fos.write(decodedString);
fos.close();
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
ContentValues values= new ContentValues();
System.out.println(values);
}
catch (java.io.IOException e)
{
Log.e("PictureDemo", "Exception in photoCallback", e);
}
}
Please suggest how to use download manager into it??? thanks
You could use a ProgressBar to accomplish this.
First, add a progressbar to your interface like this:
<ProgressBar
android:id="#+id/progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="#android:style/Widget.ProgressBar.Small"/>
Then in your code update your method like this:
protected ProgressBar mProgressBar;
protected long downloadId;
protected DownloadManager manager;
public void startdownload() {
//<SET UP DOWNLOAD MANAGER HERE>
downloadId = manager.enqueue(request);
mProgressBar = findViewById(R.id.progress_bar);
Timer myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(downloadId);
Cursor cursor = manager.query(q);
cursor.moveToFirst();
int bytes_downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
cursor.close();
int dl_progress = (bytesDownloaded * 1f / bytesTotal) * 100;
runOnUiThread(new Runnable(){
#Override
public void run(){
mProgressbar.setProgress((int) dl_progress);
}
});
}
}, 0, 10);
}
Use Follow Method
private NotificationManager mNotifyManager;
case R.id.btnSubmit:
mNotifyManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(context);
mBuilder.setContentTitle("BuyMixTapes")
.setContentText("Download in progress")
.setSmallIcon(R.drawable.appiconmain);
new DownloadFile().execute(vv);
public class DownloadFile extends AsyncTask<String, String, String> {
/**
* Before starting background thread
* Show Progress Bar Dialog
*/
#Override
protected void onPreExecute() {
super.onPreExecute();
//context.showDialog(progress_bar_type);
mBuilder.setProgress(100, 0, false);
mNotifyManager.notify(id, mBuilder.build());
}
protected String doInBackground(String... f_url) {
int count;
try {
for (int i = 0; i < f_url.length; i++) {
Log.e("0url",""+f_url[0]);
Log.e("1url",""+f_url[1]);
// Log.e("1url",""+f_url[1]);
URL url = new URL(f_url[i]);
URLConnection conection = url.openConnection();
conection.connect();
// getting file length
int lenghtOfFile = conection.getContentLength();
// input stream to read file - with 8k buffer
InputStream input = new BufferedInputStream(url.openStream(), 8192);
// Output stream to write file
// OutputStream output = new FileOutputStream("/sdcard/"+f_url[i]);
OutputStream output = new FileOutputStream(
"/sdcard/" +i + "buymix.mp3");
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
// After this onProgressUpdate will be called
publishProgress("" + (int) ((total * 100) / lenghtOfFile));
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
}
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
/**
* Updating progress bar
*/
/**
* After completing background task
* Dismiss the progress dialog
**/
#Override
protected void onProgressUpdate(String... values) {
// Update progress
mBuilder.setProgress(100, Integer.parseInt(values[0]), false);
mNotifyManager.notify(id, mBuilder.build());
super.onProgressUpdate(values);
}
protected void onPostExecute(String result) {
super.onPostExecute(result);
mBuilder.setContentText("Download complete");
// Removes the progress bar
String imagePath = Environment.getExternalStorageDirectory()
.toString() + "/downloaded.mp3";
mBuilder.setProgress(0, 0, false);
mNotifyManager.notify(id, mBuilder.build());
}
}
Update 2021:
Add a ProgressBar in your layout (TextView is just for showing more information):
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/progressBar"
android:text="Hello World!" />
Then before onCreate:
DownloadManager downloadManager;
long downloadReference;
TextView text1;
ProgressBar progressBar;
Timer progressTimer;
Afterwards, in onCreate:
text1 = (TextView) findViewById(R.id.textView1);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
Then after setting up download manager:
// <Some codes which setup download manager>
downloadReference = downloadManager.enqueue(request); // enqueue a new download
// update progressbar
progressTimer = new Timer();
progressTimer.schedule(new TimerTask() {
#Override
public void run() {
DownloadManager.Query downloadQuery = new DownloadManager.Query();
downloadQuery.setFilterById(downloadReference);
Cursor cursor = downloadManager.query(downloadQuery);
if (cursor.moveToFirst()) { // this "if" is crucial to prevent a kind of error
final int downloadedBytes = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
final int totalBytes = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)); // integer is enough for files under 2GB
cursor.close();
final float downloadProgress = downloadedBytes * 100f / totalBytes;
if(downloadProgress > 99.9) // stop repeating timer (it's also useful for error prevention)
progressTimer.cancel();
runOnUiThread(new Runnable() {
#Override
public void run() {
text1.setText(downloadedBytes + "\n" + totalBytes + "\n" + downloadProgress + "%");
progressBar.setProgress((int) downloadProgress);
}
});
}
}
}, 0, 1000);
Some tips:
If your file is larger than 2GB, you should use another type instead of int such as double etc.
You can stop timer somewhere else for example, in BroadcastReceiver if you have.
Task executions is every 1000 milliseconds (every 1 second) which is obviously changable.

Categories

Resources