i am doing research oh how to trigger my application if any of download happens in any of application. I have code snippet which uses DownloadManager and that will notify me only when my application had perform any of download, but whereas i never find any solution on which any of download happens in my mobile, that has to notify my application. Pl suggest me if this will be possible. Thanks
1- You have to make Service for Download any file in Background.
public class DownloadService extends Service {
private static final String TAG = "DownloadService";
public static final int UPDATE_PROGRESS = 8344;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent == null) {
} else {
final String urlToDownload = intent.getStringExtra("url");
final ResultReceiver receiver = (ResultReceiver) intent
.getParcelableExtra("receiver");
new Thread(new Runnable() {
#Override
public void run() {
try {
URL url = new URL(urlToDownload);
URLConnection connection = url.openConnection();
connection.connect();
int fileLength = connection.getContentLength();
// download the file
InputStream input = new BufferedInputStream(url
.openStream());
String localPath = Environment
.getExternalStorageDirectory()
.getAbsoluteFile()
+ File.separator
+ Constant.ROOT_FOLDER_NAME
+ File.separator
+ Constant.FOLDER_IMAGE
+ File.separator
+ urlToDownload.substring(urlToDownload
.lastIndexOf('/') + 1);
AppLog.Log(TAG, "Path :: " + localPath);
OutputStream output = new FileOutputStream(localPath);
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
Bundle resultData = new Bundle();
resultData.putInt("progress",
(int) (total * 100 / fileLength));
receiver.send(UPDATE_PROGRESS, resultData);
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (IOException e) {
AppLog.Log(TAG, "********* EXCEPTION *****");
e.printStackTrace();
}
Bundle resultData = new Bundle();
resultData.putInt("progress", 100);
receiver.send(UPDATE_PROGRESS, resultData);
stopSelf();
}
}).start();
}
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
2- Then you have to Make ResultReceiver to get notifying while download is completed.
private class DownloadReceiver extends ResultReceiver {
public DownloadReceiver(Handler handler) {
super(handler);
}
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
if (resultCode == DownloadService.UPDATE_PROGRESS) {
int progress = resultData.getInt("progress");
if (progress == 100) {
// Download Complete
}
}
}
}
3- Call Download Service
Intent intent = new Intent(context, DownloadService.class);
intent.putExtra("url", "url to download");
intent.putExtra("receiver", new DownloadReceiver(new Handler()));
startService(intent);
Changes in Manifest.xml
Add tag in manifest file inside Application tag:
<application >
------
------
<service android:name="PACKAGENAME.DownloadService" />
------
------
</application>
Related
I have to create an application that downloads files from a server using IntentService, I have created the Downloading Service and I pass it down to the receiver but I have no idea where to go from there.The result should be an Array String that will populate a listView through an adapter. But I don't get how I could pass the result from the receiver to the MainActivity where my adapter is.
public class MainActivity extends AppCompatActivity {
ArrayList<PlaylistItem> arrayOfUsers = new ArrayList<PlaylistItem>();
// Create the adapter to convert the array to views
PlaylistAdapter adapter = new PlaylistAdapter(this, arrayOfUsers);
// Attach the adapter to a ListView
ListView listView = (ListView) findViewById(R.id.listView);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent downloadIntent = new Intent(this, DownloadService.class);
downloadIntent.putExtra("url", "url to be called" );
downloadIntent.putExtra("type","playlist");
downloadIntent.putExtra("receiver", new DownloadReceiver(new Handler()));
startService(downloadIntent);
listView.setAdapter(adapter);
}
}
The downloadService
public class DownloadService extends IntentService {
public static final int UPDATE_PROGRESS = 1000;
public static final int PLAYLIST_READY = 2000;
private ResultReceiver receiver;
public DownloadService() {
super("DownloadService");
}
#Override
protected void onHandleIntent(Intent intent) {
String urlToDownload = intent.getStringExtra("url");
receiver = (ResultReceiver) intent.getParcelableExtra("receiver");
String type= intent.getStringExtra("type");
// se apeleaza ori downloadPlaylist ori downloadMusic
// in functie de ce url am primit in intent
if(type=="playlist")
{
downloadPlaylist(urlToDownload);
}
}
private void downloadPlaylist(String urlToDownload){
String str=null;
try {
URL url = new URL(urlToDownload);
URLConnection connection = url.openConnection();
connection.connect();
// this will be useful so that you can show a typical 0-100% progress bar
int fileLength = connection.getContentLength();
File musicDirectory = new
File(Environment.getExternalStorageDirectory(),"music");
if (!musicDirectory.exists())
musicDirectory.mkdirs();
// download the file
InputStream input = new BufferedInputStream(connection.getInputStream());
OutputStream output = new FileOutputStream(musicDirectory+urlToDownload);
str=input.toString();
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
Bundle resultData = new Bundle();
resultData.putInt("progress" ,(int) (total * 100 / fileLength));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (IOException e) {
e.printStackTrace();
}
Bundle resultData = new Bundle();
resultData.putInt("progress" ,100);
receiver.send(UPDATE_PROGRESS, resultData);
}
public class DownloadReceiver extends ResultReceiver {
public DownloadReceiver(Handler handler) {
super(handler);
}
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
if (resultCode == UPDATE_PROGRESS) {
//send data to Main ACtivity
// update progress bar
}
}
}
I don't get how I could call the array from receiver in MainActivity or vice-versa to populate it.
If you could give me an example. Thank you !
In my application, I have an expandablelistview and I want to open a PDF downloaded from the internet when I click on a specific child. The problem is that the pdf file (Read.pdf) is always empty, meaning that the download is not working.
Downloader Class:
public class Downloader {
public static void DownloadFile(String fileURL, File directory) {
try {
FileOutputStream f = new FileOutputStream(directory);
URL u = new URL(fileURL);
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
InputStream in = c.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = in.read(buffer)) > 0) {
f.write(buffer, 0, len1);
}
f.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Part of the Activity:
private void registerClick() {
expListView.setOnChildClickListener(new OnChildClickListener() {
#Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
if ((groupPosition == 0) && (childPosition == 0)){
File file = new File(Environment.getExternalStorageDirectory()+File.separator+"IAVE", "Read.pdf");
try {
file.createNewFile();
} catch (IOException e1) {
e1.printStackTrace();
}
Downloader.DownloadFile("https://www.cp.pt/StaticFiles/Passageiros/1_horarios/horarios/PDF/lx/linha_cascais.pdf", file);
AbrirPDF.showPdf();
} else {
}
return false;
}
});
}
I think the OpenPDF (AbrirPDF) doesn't have any problem, but I will post it...
public class AbrirPDF {
public static void showPdf()
{
File file = new File(Environment.getExternalStorageDirectory()+File.separator+"IAVE/Read.pdf");
PackageManager packageManager = ContextGetter.getAppContext().getPackageManager();
Intent testIntent = new Intent(Intent.ACTION_VIEW);
testIntent.setType("application/pdf");
List list = packageManager.queryIntentActivities(testIntent, PackageManager.MATCH_DEFAULT_ONLY);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri uri = Uri.fromFile(file);
intent.setDataAndType(uri, "application/pdf");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ContextGetter.getAppContext().startActivity(intent);
}
}
Thank you.
Ideally, your download should happen in a separate thread to avoid locking your app.
Here is an example that also includes a progress bar.
public class MainActivity extends Activity {
private ProgressDialog pDialog;
public static final int progress_bar_type = 0;
private static String file_url = "https://www.cp.pt/StaticFiles/Passageiros/1_horarios/horarios/PDF/lx/linha_cascais.pdf";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new DownloadFileFromURL().execute(file_url);
}
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case progress_bar_type: // we set this to 0
pDialog = new ProgressDialog(this);
pDialog.setMessage("Downloading file. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setMax(100);
pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pDialog.setCancelable(true);
pDialog.show();
return pDialog;
default:
return null;
}
}
class DownloadFileFromURL extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialog(progress_bar_type);
}
#Override
protected String doInBackground(String... f_url) {
int count;
try {
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.connect();
// this will be useful so that you can show a tipical 0-100%
// progress bar
int lenghtOfFile = conection.getContentLength();
// download the file
InputStream input = new BufferedInputStream(url.openStream(),
8192);
// Output stream
OutputStream output = new FileOutputStream(Environment
.getExternalStorageDirectory().toString()
+ "/2011.kml");
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;
}
protected void onProgressUpdate(String... progress) {
// setting progress percentage
pDialog.setProgress(Integer.parseInt(progress[0]));
}
#Override
protected void onPostExecute(String file_url) {
// dismiss the dialog after the file was downloaded
dismissDialog(progress_bar_type);
}
}
}
I am using a foreground service to perform long I/O operations (upload of files) with a server via a tcp socket.
Inside the service I am using an AsynTask to be able to publish the transfer progress to the UI (notification or whatever else, I don't really mind).
The problem is whenever the app is swiped from recent apps, the socket seems to get closed as well. This is completely contradictory to everything I have read and tested regarding foreground services (like the music app when I swipe it, it displays a foreground service notification and music keeps playing without a glitch).
So what am I doing wrong?
here is my service code:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
Log.i(TAG, "StorageServerProxyService started");
final Intent intentForThread = intent;
new Thread() {
#Override
public void run() {
if (intentForThread != null)
{
String action = intentForThread.getAction();
Log.i(TAG, "Action:" + action);
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
try {
connectIfNecessary();
switch (action) {
case ACTION_UPLOAD: {
startServiceForeground();
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG + "_wakeLock");
wakeLock.acquire();
String destId = intentForThread.getStringExtra(DESTINATION_ID);
FileManager managedFile = (FileManager) intentForThread.getSerializableExtra(FILE_TO_UPLOAD);
uploadFileToServer(destId, managedFile);
releaseLockIfNecessary();
stopForeground(true);
}
break;
default:
Log.w(TAG, "Service started with action:" + action);
}
} catch (IOException e) {
e.printStackTrace();
String errMsg = "Action failed:"+action+" Exception:"+e.getMessage();
Log.e(TAG, errMsg);
handleDisconnection(errMsg);
}
} else
Log.w(TAG, "Service started with missing action");
}
}.start();
return START_NOT_STICKY;
}
public void uploadFileToServer(final String destNumber, final FileManager managedFile) throws IOException {
TransferDetails td = new TransferDetails(SharedConstants.MY_ID, destNumber, managedFile);
new UploadTask(getApplicationContext(), connectionToServer).execute(td);
}
private void startServiceForeground() {
Notification notification = new Notification(android.R.drawable.stat_sys_upload, getText(R.string.upload_ticker_text),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, StorageServerProxyService.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
}
This is the AsynTask (UploadTask) code:
public class UploadTask extends AsyncTask<TransferDetails,String,Void> {
private NotificationHelper mNotificationHelper;
private static final String TAG = UploadTask.class.getSimpleName();
private ConnectionToServer _connectionToServer;
private TransferDetails _td;
private Context _context;
public UploadTask(Context context, ConnectionToServer connectionToServer){
_context = context;
mNotificationHelper = new NotificationHelper(_context);
_connectionToServer = connectionToServer;
}
protected void onPreExecute(){
//Create the notification in the statusbar
mNotificationHelper.createUploadNotification();
}
#Override
protected Void doInBackground(TransferDetails... details) {
_td = details[0];
FileManager managedFile = _td.get_managedFile();
MessageUploadFile msgUF = new MessageUploadFile(_td.getSourceId(),_td);
try {
_connectionToServer.sendToServer(msgUF);
Log.i(TAG, "Initiating file data upload...");
DataOutputStream dos = new DataOutputStream(_connectionToServer.getClientSocket().getOutputStream());
FileInputStream fis = new FileInputStream(managedFile.getFile());
BufferedInputStream bis = new BufferedInputStream(fis);
byte[] buf = new byte[1024 * 8];
long fileSize = managedFile.getFileSize();
long bytesToRead = fileSize;
int bytesRead;
while (bytesToRead > 0 && (bytesRead = bis.read(buf, 0, (int) Math.min(buf.length, bytesToRead))) != -1) {
dos.write(buf, 0, bytesRead);
String msg = "File upload to:"+_td.getDestinationId()+" %.0f%% complete";
float percent = (float) (fileSize - bytesToRead) / fileSize * 100;
publishProgress(String.format(msg, percent));
bytesToRead -= bytesRead;
}
}
catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "Failed:" + e.getMessage());
}
return null;
}
protected void onProgressUpdate(String... progress) {
//This method runs on the UI thread, it receives progress updates
//from the background thread and publishes them to the status bar
mNotificationHelper.progressUpdate(progress[0]);
}
protected void onPostExecute(Void result) {
//The task is complete, tell the status bar about it
mNotificationHelper.completed();
}
}
So I'm try to make service in Android app, this is my first App on android (& on Java too)), so i have a great number of problems. But the main problem is "architecture" my background service.
I need to set a connection via Bluetooth to device (My custom device). I have my own protocol (still in progress), and so I need in my Background service for the following things:
Sent something
Always listen to InputStream! (all the time)
How i can create this to things in my service?
I need to create two thread's in my service?
I have tried a lot of "ideas" as to how to? and I have very huge "dirty" code... and every time I run it, it crashes.
public class MyService extends Service {
public BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
public BluetoothSocket socket;
public String readMessage;
public int BTC_STATE;
ExecutorService es;
public void onCreate() {
super.onCreate();
es = Executors.newFixedThreadPool(2);
}
}
public void onDestroy() {
super.onDestroy();
}
// ЗАПУСК СЕРВИСА
public int onStartCommand(Intent intent, int flags, int startId) {
int time = intent.getIntExtra(DashboardActivity.PARAM_TIME, 1);
int task = intent.getIntExtra(DashboardActivity.PARAM_TASK, 0);
String strMAC = intent.getStringExtra(DashboardActivity.PARAM_MAC);
String strMESS = intent.getStringExtra(DashboardActivity.PARAM_MESSAGE);
MyRun mr = new MyRun(startId, time, task,strMAC,strMESS);
es.execute(mr);
return super.onStartCommand(intent, flags, startId);
}
public IBinder onBind(Intent arg0) {
return null;
}
class MyRun implements Runnable {
int time;
int startId;
int task;
int target;
String strMAC;
String strMESS;
public MyRun(int startId, int time, int task,String strMAC,String strMESS) {
this.time = time;
this.startId = startId;
this.task = task;
this.target = 1;
this.strMAC = strMAC;
this.strMESS = strMESS;
}
public void run() {
Intent intent = new Intent(DashboardActivity.BROADCAST_ACTION);
//here, depending on task id i sent reqwest. But where i need to create listning method?
}
In run() i have different tasks... But where i need to create listning method for my BTE socket InPutStream ?
So no i have 3 task for service:
1)connect
2)start listening to inputStream of my BTE connection
3)to sent data
try {
InputStream is = socket.getInputStream();
byte[] buffer = new byte[1];
int bytes;
//StringBuilder readMessage = new StringBuilder();
String readMess2;
while (1!=2) {
try {
bytes = is.read(buffer);
String readed = new String(buffer, 0, bytes);
//readMessage.append(readed);
readMess2=readed;
intent.putExtra(DashboardActivity.PARAM_STATUS, DashboardActivity.STATUS_FINISH);
intent.putExtra(DashboardActivity.PARAM_RESULT, "Listning: " + readMess2);
sendBroadcast(intent);
} catch (IOException e) {
BTC_STATE='0';
intent.putExtra(DashboardActivity.PARAM_STATUS, DashboardActivity.STATUS_FINISH);
intent.putExtra(DashboardActivity.PARAM_RESULT, "Ошибка уха!");
sendBroadcast(intent);
serviceNotifer("ADPTTO Service", "УХО ОШИБКА " + BTC_STATE);
break;
}
}
intent.putExtra(DashboardActivity.PARAM_STATUS, DashboardActivity.STATUS_FINISH);
intent.putExtra(DashboardActivity.PARAM_RESULT, "STOP УХО WHILE =)");
sendBroadcast(intent);
serviceNotifer("ADPTTO Service", "УХО WHILE OUT " + BTC_STATE);
} catch (IOException e) {
BTC_STATE='0';
intent.putExtra(DashboardActivity.PARAM_STATUS, DashboardActivity.STATUS_FINISH);
intent.putExtra(DashboardActivity.PARAM_RESULT, "GET ERROR");
sendBroadcast(intent);
serviceNotifer("ADPTTO Service", "УХО ОШИБКА 2 + " + BTC_STATE);
}
This code is working.. but just for sometime (1-2 min). Who i can listen to all the time?
I download an image from the internet with a service. When the download is complete it changes the textview. I tried this on my device and it works.
Now i want the imageview in my layout to change to the downloaded image.
ServiceFile java
public class ServiceFile extends IntentService {
private int result = Activity.RESULT_CANCELED;
public static final String URL = "urlpath";
public static final String FILENAME = "filename";
public static final String FILEPATH = "filepath";
public static final String RESULT = "result";
public static final String NOTIFICATION = "be.ehb.arnojansens.fragmentexampleii";
public ServiceFile() {
super("ServiceFile");
}
// will be called asynchronously by Android
#Override
protected void onHandleIntent(Intent intent) {
String urlPath = intent.getStringExtra(URL);
String fileName = intent.getStringExtra(FILENAME);
File output = new File(Environment.getExternalStorageDirectory(),
fileName);
if (output.exists()) {
output.delete();
}
InputStream stream = null;
FileOutputStream fos = null;
try {
java.net.URL url = new URL(urlPath);
stream = url.openConnection().getInputStream();
InputStreamReader reader = new InputStreamReader(stream);
fos = new FileOutputStream(output.getPath());
int next = -1;
while ((next = reader.read()) != -1) {
fos.write(next);
}
// successfully finished
result = Activity.RESULT_OK;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
publishResults(output.getAbsolutePath(), result);
}
private void publishResults(String outputPath, int result) {
Intent intent = new Intent(NOTIFICATION);
intent.putExtra(FILEPATH, outputPath);
intent.putExtra(RESULT, result);
sendBroadcast(intent);
}
}
This is my main activity where i have my textview and the future imageview
private TextView textView;
private ImageView imageView;
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
String string = bundle.getString(ServiceFile.FILEPATH);
int resultCode = bundle.getInt(ServiceFile.RESULT);
if (resultCode == RESULT_OK) {
Toast.makeText(MainActivity.this,
"Download complete. Download URI: " + string,
Toast.LENGTH_LONG).show();
textView.setText("Download done");
// here i shoud load my image i downloaded with my service
} else {
Toast.makeText(MainActivity.this, "Download failed",
Toast.LENGTH_LONG).show();
textView.setText("Download failed");
}
}
}
};
public void service (View view) {
Intent intent = new Intent(this, ServiceFile.class);
// add infos for the service which file to download and where to store
intent.putExtra(ServiceFile.FILENAME, "index.html");
intent.putExtra(ServiceFile.URL,
"http://en.wikipedia.org/wiki/Star_Wars#mediaviewer/File:Star_Wars_Logo.svg");
startService(intent);
textView.setText("Service started");
}
Better to use Picasso or Universal Image Loader than to pass the information per Intent.
If not, your service should write the image into a readable folder and you can send by intent the Uri to that file to whom it concerns with EventBus for instance