I have this code with wich I download APK expension file
private void performAPKExpansionCheckAndDownload(){
String APK_LOG = "APK_LOG";
String mainFileName = Helpers.getExpansionAPKFileName(this, true, 2);
Log.d(APK_LOG,"mainFileName "+mainFileName);
boolean fileExists = Helpers.doesFileExist(this, mainFileName, 38783430L, false);
Log.d(APK_LOG,"fileExists "+fileExists);
if (!fileExists) {
Intent launcher = getIntent();
Intent fromNotification = new Intent(this, getClass());
fromNotification.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
fromNotification.setAction(launcher.getAction());
if (launcher.getCategories() != null) {
for (String cat : launcher.getCategories()) {
Log.d(APK_LOG,"cat "+cat);
fromNotification.addCategory(cat);
}
}
PendingIntent pendingIntent = PendingIntent.getActivity(
this, 0, fromNotification, PendingIntent.FLAG_UPDATE_CURRENT);
try {
int result = DownloaderClientMarshaller.startDownloadServiceIfRequired(
this, pendingIntent, MyDownloaderService.class);
Log.d(APK_LOG,"result "+result);
if (DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED != result) {
// implement Downloading UI.
return;
}
} catch (NameNotFoundException e) {
Log.e("apk-expansion-files", "NameNotFoundException occurred. " + e.getMessage(), e);
}
}
}
The problem is that I need to handle callbacks like onDownloadFinished and onProgressUpdate. I know that thous messages are posted somewhere but I don't know how to handle them. Since I haven't worked with messages in Android any help would be good.
UPDATE:
All downloading happens here:
int result = DownloaderClientMarshaller.startDownloadServiceIfRequired(
this, pendingIntent, MyDownloaderService.class);
if (DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED != result) {
// implement Downloading UI.
return;
}
I guess those callbacks must be connected to that DownloaderClientMarshaller class.
Related
I have an intent service which is processing long running task. But while processing if an exception occurs lets say SocketTimeOutException the service stops. How to catch the exception and restart the process.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
#Override
protected void onHandleIntent(Intent intent) {
String name = intent.getStringExtra("name");
String packageName = intent.getStringExtra("packageName");
String path = intent.getStringExtra("path");
int downloadedSoFar = 0;
Intent i = new Intent(getApplicationContext(), DownloadListViewApp.class);
PendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0, i, 0);
nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this);
mBuilder.setContentTitle(name)
.setContentText("Download in progress")
.setSmallIcon(R.drawable.logo).setContentInfo("0%").setContentIntent(pi);
mBuilder.setOngoing(true);
try {
url = new URL(IPClass.SERVERIP + path + "/" + packageName);
connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setReadTimeout(7000);
int fileLength = connection.getContentLength();
connection.connect();
input = connection.getInputStream();
output = new FileOutputStream("/sdcard/Android/appdata/tmp/downloadtmp/" + packageName, true);
byte data[] = new byte[1024];
int count;
boolean continueLoop = true;
while ((count = input.read(data)) > 0 && continueLoop) {
progressChange((int) (downloadedSoFar * 100L) / fileLength, packageName);
downloadedSoFar = downloadedSoFar + count;
output.write(data, 0, count);
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
if (output != null) output.close();
if (input != null) input.close();
} catch (IOException ignored) {
}
if (connection != null) {
connection.disconnect();
}
}
You can't stop intent service till its duty has completed, if you want to stop it then you should have to stop alarm manager in intent service like this.
Intent DataSyncing = new Intent(getBaseContext(), DataSyncingScheduledReceiver.class);
DataSyncing.setAction(DataSyncingScheduledReceiver.ACTION_DATASYNC_RECEIVER);
PendingIntent DataSyncingIntent = PendingIntent.getBroadcast(getBaseContext(),1003, DataSyncing, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManagerdatasync = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManagerdatasync.cancel(DataSyncingIntent);
DataSyncingIntent.cancel();
Ref :- https://stackoverflow.com/a/12776012/2705391
You can use this for your problem.
#Override
protected void onHandleIntent(Intent intent)
{
try
{
// STOP SERVICE
// DO YOUR WORK HERE
}
finally
{
// START SERVICE
}
}
I think restarting a servise is not a solution you should handle it in catch
put your code to call api inside seperate function
supose your function is like callAPI()
} catch (final java.net.SocketTimeoutException e) {
// connection timed out...let's try again
callAPI()
}
This creates a recursion
by this your api will be called n time untill your api will give SocketTimeoutException
so you will not need to restart your IntentService. it will remain onrun until your api executed
if you want to prevent this you have to specify and implement logic of nuberofAttempts as in volley
volley inbuilt has retry policy you should read about it.
else i sugest volley or retrofit to use
I wrote a custom plugin to read blocks of data from an NfcA(i.e.non-ndef) tag. It seems to work fine , but only after the second scan. I am using Activity intent to derive the "NfcAdapter.EXTRA_TAG" to later use it for reading the values. I am also updating the Intents in onNewIntent(). OnNewIntent gets called after the second scan and after that I get result all the time.But in the first scan onNewIntent does not gets called, hence I end up using the Activity tag that does not have "NfcAdapter.EXTRA_TAG", hence I get null. Please see the my code below.
SE_NfcA.java(my native code for plugin)
#Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
String Result = "";
String TypeOfTalking = "";
if (action.contains("TalkToNFC"))
{
JSONObject arg_object = args.getJSONObject(0);
TypeOfTalking = arg_object.getString("type");
if(TypeOfTalking != "")
{
if (TypeOfTalking.contains("readBlock"))
{
if(TypeOfTalking.contains("#"))
{
try
{
String[] parts = TypeOfTalking.split("#");
int index = Integer.parseInt(parts[1]);
Result = Readblock(cordova.getActivity().getIntent(),(byte)index);
callbackContext.success(Result);
}
catch(Exception e)
{
callbackContext.error("Exception Reading "+ TypeOfTalking + "due to "+ e.toString());
return false;
}
}
}
else
{
return false;
}
}
else
{
return false;
}
}
else
{
return false;
}
return true;
}
#Override
public void onNewIntent(Intent intent) {
ShowAlert("onNewIntent called");
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
super.onNewIntent(intent);
getActivity().setIntent(intent);
savedTag = tagFromIntent;
savedIntent = intent;
}
#Override
public void onPause(boolean multitasking) {
Log.d(TAG, "onPause " + getActivity().getIntent());
super.onPause(multitasking);
if (multitasking) {
// nfc can't run in background
stopNfc();
}
}
#Override
public void onResume(boolean multitasking) {
Log.d(TAG, "onResume " + getActivity().getIntent());
super.onResume(multitasking);
startNfc();
}
public String Readblock(Intent Intent,byte block) throws IOException{
byte[] response = new byte[]{};
if(Intent != null)
{
Tag myTag = Intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if(savedTag != null)
myTag = savedTag;
if(myTag != null)
{
try{
Reader nTagReader = new Reader(myTag);
nTagReader.close();
nTagReader.connect();
nTagReader.SectorSelect(Sector.Sector0);
response = nTagReader.fast_read(block, block);
nTagReader.close();
return ConvertH(response);
}catch(Exception e){
ShowAlert(e.toString());
}
}
else
ShowAlert("myTag is null.");
}
return null;
}
private void createPendingIntent() {
if (pendingIntent == null) {
Activity activity = getActivity();
Intent intent = new Intent(activity, activity.getClass());
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP| Intent.FLAG_ACTIVITY_CLEAR_TOP);
pendingIntent = PendingIntent.getActivity(activity, 0, intent, 0);
}
}
private void startNfc() {
createPendingIntent(); // onResume can call startNfc before execute
getActivity().runOnUiThread(new Runnable() {
public void run() {
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(getActivity());
if (nfcAdapter != null && !getActivity().isFinishing()) {
try {
nfcAdapter.enableForegroundDispatch(getActivity(), getPendingIntent(), getIntentFilters(), getTechLists());
if (p2pMessage != null) {
nfcAdapter.setNdefPushMessage(p2pMessage, getActivity());
}
} catch (IllegalStateException e) {
// issue 110 - user exits app with home button while nfc is initializing
Log.w(TAG, "Illegal State Exception starting NFC. Assuming application is terminating.");
}
}
}
});
}
private void stopNfc() {
Log.d(TAG, "stopNfc");
getActivity().runOnUiThread(new Runnable() {
public void run() {
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(getActivity());
if (nfcAdapter != null) {
try {
nfcAdapter.disableForegroundDispatch(getActivity());
} catch (IllegalStateException e) {
// issue 125 - user exits app with back button while nfc
Log.w(TAG, "Illegal State Exception stopping NFC. Assuming application is terminating.");
}
}
}
});
}
private Activity getActivity() {
return this.cordova.getActivity();
}
private PendingIntent getPendingIntent() {
return pendingIntent;
}
private IntentFilter[] getIntentFilters() {
return intentFilters.toArray(new IntentFilter[intentFilters.size()]);
}
private String[][] getTechLists() {
//noinspection ToArrayCallWithZeroLengthArrayArgument
return techLists.toArray(new String[0][0]);
}
}
My index.js file
nfc.addTagDiscoveredListener(
function(nfcEvent){
console.log(nfcEvent.tag.id);
alert(nfcEvent.tag.id);
window.echo("readBlock#88");//call to plugin
},
function() {
alert("Listening for NFC tags.");
},
function() {
alert("NFC activation failed.");
}
);
SE_NfcA.js(plugin interface for interaction b/w index.js and SE_NfcA.java)
window.echo = function(natureOfTalk)
{
alert("Inside JS Interface, arg =" + natureOfTalk);
cordova.exec(function(result){alert("Result is : "+result);},
function(error){alert("Some Error happened : "+ error);},
"SE_NfcA","TalkToNFC",[{"type": natureOfTalk}]);
};
I guess I have messed up with the Intents/Activity Life-Cycle, please help. TIA!
I found a tweak/hack and made it to work.
Before making any call to read or write, I made one dummy Initialize call.
window.echo("Initialize");
window.echo("readBlock#88");//call to plugin to read.
And in the native code of the plugin, on receiving the "Initialize" token I made a startNFC() call.
else if(TypeOfTalking.equalsIgnoreCase("Initialize"))
{
startNfc();
}
In my app i have started download service,it is working fine in background.During download my testing team doing force stop and clear data or Uninstall.But After uninstall or clear data still my Download service is running in background.During download i have installed the same app again but it is misbehaving some thing.While uninstall or clear data or force stop i have to cancel the download How?
public class FileDownloaderService extends IntentService {
private CarcarePreferences preferences;
public FileDownloaderService() {
super("FileDownloaderService");
}
#Override
public void onCreate() {
super.onCreate();
preferences = CarcarePreferences.getCarcarePreferencesObject(getApplicationContext());
DBHelper.getInstance(getApplicationContext()).open();
downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
}
#Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
if (extras == null) {
return;
}
if (extras.containsKey("ResultReceiver")) {
resultReceiver = extras.getParcelable("ResultReceiver");
}
if (extras.containsKey("ContentToDownload")) {
contentToDownload = extras.getInt("ContentToDownload");
} else {
return;
}
if (contentToDownload != Carcare.ContentToDownload.IMAGES) {
isDefaultVehicle = extras.getBoolean("IsDefaultVehicle");
fetchVehicle();
}
switch (contentToDownload) {
case Carcare.ContentToDownload.HEADUNIT_IMAGES:
if (extras.containsKey("HeadUnits")) {
headUnits = (ArrayList<Unit>) extras.getSerializable("Units");
downloadHeadUnits();
resultReceiver.send(0, null);
}
break;
}
}
private void fetchVehicle() {
Object[] objects;
if (isDefaultVehicle) {
objects = DBAdapter.getAllVehicles(preferences.getDefaultModel(),
preferences.getDefaultYear(), isDefaultVehicle);
} else {
objects = DBAdapter.getAllVehicles(preferences.getCurrentModel(),
preferences.getCurrentYear(), isDefaultVehicle);
}
vehicle = (Vehicle) objects[0];
}
private void downloadHeadUnits() {
mHeadUnitDir = SdUtils.getDir(this);
//clearHeadUnits();
for (CUnit unit : Units) {
String fileName = mDir + "/" + unit.getGuid() + ".png";
InputStream stream = null;
final HttpGet httpRequest = new HttpGet(unit.getHuImageUrl());
httpRequest.setHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_KEEP_ALIVE);
try {
File file = new File(fileName);
if (!file.exists()) {
FileOutputStream out = new FileOutputStream(file); //openFileOutput(fileName);
stream = new DefaultHttpClient().execute(httpRequest).getEntity().getContent();
Bitmap bitmap = BitmapFactory.decodeStream(stream);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
}
} catch (IOException ex) {
ex.printStackTrace();
} catch (IllegalStateException ex) {
ex.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void download() {
cancelDownload(Carcare.FileType.QRG, vehicle.getPath());
deleteDoc(vehicle.getQRGPath());
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(vehicle.getUrl()));
request.setDestinationUri(Uri.parse(vehicle.getPath()));
request.setTitle("Unit");
request.setDescription("Quick Reference Guide");
preferences.setDownloadID(Carcare.FileType.QRG, downloadManager.enqueue(request));
}
}
You must use a Service.
In the Service's onDestroy(), you can write the code to finish the DownloadManager.
The Service will be killed before the app is about to uninstall.
This way the Download will stop.
Take a look at the remove() method of the DownloadManager.
It says:
public int remove (long... ids) Added in API level 9
Cancel downloads and remove them from the download manager. Each
download will be stopped if it was running, and it will no longer be
accessible through the download manager. If there is a downloaded
file, partial or complete, it is deleted. Parameters ids the IDs of
the downloads to remove Returns
the number of downloads actually removed
Edit
To intercept your application uninstall take a look at this answer.
We have an app in the Google Play Store that runs in the foreground continuously. The devices that it runs on are out of our control and are not rooted. They run on either Android 4.2 or 4.4.
Our goal is to have the app update to the newest version that we release via the Play Store without user interaction. Restarting the device would be the only acceptable "interaction" option.
We find that a running app does not updated automatically when it is running even if the "automatic update" is turned on.
What is the way to achieve our goal?
Use an Alarm Manager to scheduled your update and then use a create a class and extend the service or IntentService class. Check if theres an internet connection if yes proceed to update like this: Check this link Android Services - Tutorial In this way you can update even not showing your Activity by using service.
Creating the Alarm Manager:
Calendar cal = Calendar.getInstance();
Intent intent = new Intent(this, MyService.class);
PendingIntent pintent = PendingIntent.getService(this, 0, intent, 0);
AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
// Start every 30 seconds
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 30*1000, pintent);
For service:
public class DownloadService 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 = "com.vogella.android.service.receiver";
public DownloadService() {
super("DownloadService");
}
// 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 {
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);
}
}
I am trying to build an application in which I Am playing videos and images simultaneously. Every one hour or so the app has to download materials from internet. so to use the new materials I am trying to make it restart. I have implemented a runnable and put the code for download and restart in the run method. The problem is that the app freezes soon after start-
synchronized public void run() {
download("http://www.justieltsshaddi.com/pankaj/list.txt",
Environment.getExternalStorageDirectory() + "/alpha/list.txt");
File beta = new File(Environment.getExternalStorageDirectory()
+ "/beta/");
File betalist = new File(beta + "/list.txt");
File alpha = new File(Environment.getExternalStorageDirectory()
+ "/alpha/");
File alphalist = new File(alpha + "/list.txt");
if (alphalist.lastModified() == betalist.lastModified()) {
return;
}
try {
FileReader inAlpha = new FileReader(alphalist);
BufferedReader br = new BufferedReader(inAlpha);
String s;
Toast.makeText(this, "Starting Download...", Toast.LENGTH_SHORT)
.show();
while ((s = br.readLine()) != null) {
download("http://www.justieltsshaddi.com/pankaj" + "/" + s,
Environment.getExternalStorageDirectory() + "/alpha/"
+ s);
}
// stop the activity to rename folders
Toast.makeText(this, "Download done. Restarting...",
Toast.LENGTH_SHORT).show();
Log.d("Pankaj", "Download Done");
Intent intent = getIntent();
overridePendingTransition(0, 0);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
finish();
Log.d("Pankaj", "MainActivity Killed");
// rename alpha to beta
deleteSubFolders(beta.toString());
alpha.renameTo(beta);
if (!alpha.exists()) {
alpha.mkdir();
}
File upper = new File(alpha + "/upper/");
if (!upper.exists())
upper.mkdirs();
File lower = new File(alpha + "/lower/");
if (!lower.exists())
lower.mkdirs();
// restart the activity
overridePendingTransition(0, 0);
startActivity(intent);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
any help is appreciated. thanks in advance.
I would suggest you use Aysnc Task to download the files
private class DownloadFile extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... sUrl) {
try {
//do your download
while ((s = br.readLine()) != null) {
download("http://www.justieltsshaddi.com/pankaj" + "/" + s,
Environment.getExternalStorageDirectory() + "/alpha/"
+ s);
}
} catch (Exception e) {
}
return null;
}
call the download task as below
// execute this when the downloader must be fired
DownloadFile downloadFile = new DownloadFile();
downloadFile.execute("the url to the file you want to download");
may be thinking of firing the download task in loop.
Use Service and Alarm Manager
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 10);
Intent intent = new Intent(this, reciever.class);
PendingIntent pi = PendingIntent.getBroadcast(context, _id, i, 0);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
//for 30 mint 60*60*1000
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
60*60*1000, pi );
In broadcast reciever start the service
public class reciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
}