Android Download Manager, COLUMN_STATUS is 7. What does this means? - android

I'm trying to download a zip file which is nearly 200MB in size. In order for me to get the current downloaded bytes I use following code snippet.
while ((cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_PENDING) ||(cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_RUNNING)) {
downloadedLength = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
}
Every time (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS) returns me int 7.
What I want to achieve through this is to get the download progress until it reaches the status SUCCESS

If I'm understanding correctly, you want to show progress inside your app.
Once you have the cursor object, you can basically do this to show progress.
Cursor c = dm.query(query);
if (c.moveToFirst()) {
int totalSizeIndex = c.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
int downloadedIndex = c.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
long totalSize = c.getInt(totalSizeIndex);
long downloaded = c.getInt(downloadedIndex);
double progress = 0.0;
if (size != -1) {
progress = downloaded * 100.0 / totalSize;
}
}
downloaded * 100.0 / totalSize calculates the percentage.

7 is the index aka column number for the STATUS value.
You need to call cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) to get the actual value of the column

Related

The entire object data is not displayed in logcat android

In the Android Studio program, when printing the object, it is cut off due to the length of the data. How can I print the matrix without any cuting?
enter image description here
On the left side of the Logcat window enable the Soft-Wrap:
To print a lengthy string in logcat, use this piece of code. Here s is the string which is to be printed. I tried this code where s is given as a sample text of 1000 words and was successfully displayed Logcat.
In java,
final int maxSize = 2048;
for (int i = 0; i < s.length(); i += maxSize) {
Log.d("largeString", s.substring(i, Math.min(s.length(), i + maxSize)));
}
In Kotlin,
val maxSize = 2048
var i = 0
while (i < s.length) {
Log.d("yeyey", s.substring(i, Math.min(s.length, i + maxSize)))
i += maxSize
}
Try this code and hope this works for you.

Calculate earlier and later times, then compare with a given time

I need to calculate if a certain time is between 30 minutes earlier and 20 minutes later than the current time.
Any idea how to do this?
The problem is when the time is 23:50h, for example. So I can't do a simple comparison since 23 is greater than 00. But I must consider it smaller since it's another day.
Example:
Now is 23:45. Testing 23:50.
23:45 - 30 minutes = 23:15.
23:45 + 20 minutes = 00:05.
Is 23:50 between 23:15 and 00:05?
Another example:
Now is 00:05. Testing 00:15.
00:05 - 30 minutes = 23:35.
00:05 + 20 minutes = 00:25.
Is 00:15 between 23:35 and 00:25?
--
minSdkVersion is 22, and this further limits the available solutions.
The easiest way to go is :
Compare Hours separately from minutes.
Or also you can take the Hours, multiply them for 60 and then add the returning value to the minutes amount, that will end up with a "only minute" calculation between the 2 times. You can make whatever operation you need.
The only case you should calculate is that one you are in a different day, but that dipends and what you are trying to accomplish!
CODE IN JAVA (OLD VERSION):
public class Main
{
public static void main(String[] args)
{
//Input TIME
String date = "23.45";
//Calculating the TIME in MINUTES ONLY
int date_m = normalizeTime(date);
//CALCULATE MAX AND MIN TIMES
int max = date_m+20;
int min = date_m-30;
/*
Working like that we don't
need to worry about the day Before or After
*/
//JUST DEBUG PRINTS TO SHOW YOU THAT
System.out.println("MAX TIME : "+max);
System.out.println("MIN TIME : "+min);
//The TIME that has to be tested
String testDate = "23.50";
//Calculating the TIME in MINUTES ONLY
int testDate_m = normalizeTime(testDate);
//JUST A DEBUG PRINT TO SHOW YOU THE TESTED TIME
System.out.println("TESTED TIME : "+testDate_m);
/*
If the testDate_m is Between the MAX and MIN values it's
TRUE else it's FALSE
If needed you can adjust with >= or <=
That doesn't matter for the logic.
*/
if(testDate_m<max && testDate_m>min)
System.out.println("IT IS BETWEEN!");
else
System.out.println("IT ISN'T BETWEEN!");
//DONE!
}
/*
Just a Method to clean up the code:
Basically it will Split the string in HOURS and MINUTES
and it will make a simple operation of : Hour*60(Transforming it to minutes) + minutes
The return is an INT that represent the inserted TIME as a MINUTE ONLY TIME.
If the returned number is more than 24*60 it's the Day Next (don't need to worry about that)
If the returned number is less than 0 it's the Previous Day (don't need to worry about that)
*/
private static int normalizeTime(String time)
{
int h = Integer.parseInt(time.substring(0,2));
int m = Integer.parseInt(time.substring(3,5));
return h*60+m;
}
}
CODE IN JAVA (NEW VERSION) :
public class Main
{
public static void main(String[] args)
{
boolean inTime = true;
//Input TIME
String date = "23.50";
//Calculating the TIME in MINUTES ONLY
int date_m = normalizeTime(date);
//CALCULATE MAX AND MIN TIMES
int max = date_m+20;
int min = date_m-30;
int prevMin = max;
int nextMax = min;
if(min<0)
{
prevMin = 24*60+min;
nextMax = 24*60+max;
}
else if(max>24*60)
{
prevMin = min-24*60;
nextMax = max-24*60;
}
/*
Working like that we don't
need to worry about the day Before or After
*/
//JUST DEBUG PRINTS TO SHOW YOU THAT
System.out.println("Between :"+min+" and "+max);
System.out.println("OR");
System.out.println("Between : "+prevMin+" and "+nextMax);
//The TIME that has to be tested
String testDate = "00.05";
//Calculating the TIME in MINUTES ONLY
int testDate_m = normalizeTime(testDate);
//JUST A DEBUG PRINT TO SHOW YOU THE TESTED TIME
System.out.println("TESTED TIME : "+testDate_m);
/*
If the testDate_m is Between the MAX and MIN values it's
TRUE else it's FALSE
If needed you can adjust with >= or <=
That doesn't matter for the logic.
*/
if((testDate_m<max && testDate_m>min) || (testDate_m<nextMax && testDate_m>prevMin))
System.out.println("IT IS BETWEEN!");
else
System.out.println("IT ISN'T BETWEEN!");
//DONE!
}
/*
Just a Method to clean up the code:
Basically it will Split the string in HOURS and MINUTES
and it will make a simple operation of : Hour*60(Transforming it to minutes) + minutes
The return is an INT that represent the inserted TIME as a MINUTE ONLY TIME.
If the returned number is more than 24*60 it's the Day Next (don't need to worry about that)
If the returned number is less than 0 it's the Previous Day (don't need to worry about that)
*/
private static int normalizeTime(String time)
{
int h = Integer.parseInt(time.substring(0,2));
int m = Integer.parseInt(time.substring(3,5));
return h*60+m;
}
}
The easiest way is just to work with timestamps.
long time = new Date().getTime();
long thiry_earlier = time - minutes_to_ms(30);
long twenty_later = time + minutes_to_ms(20);
if(compare < twenty_later && compare > thirty_earlier) {
//do whatever
}
long minutes_to_ms(long minutes) {
return minutes*60*1000;
}
There's some nicer conversion functions you can use nowdays I'm just too lazy to look them up. But working with raw timestamps makes everything easier for comparisons.

Converting string with time to minutes

I am working on an Android app that gets a time (duration) value as string.
For example, the app can get a value like: 6 hours 43 mins
or a value like: 15 mins
I am looking for a way to convert this strings to an integer value in minutes.
I have tried using this function, but I canĀ“t extract the needed values:
str = str.replaceAll("[^\\d.]", "");
Edit:
it could be possible a result like 6 hours, the only known condition is that minutes are always rounded to an integer, the minimum value is 1 min
Using a Regex to get each couple numeric/time_unit. You can easily parse that with :
(\\d+) (\\w+)
Group 1 : numeric value
Group 2 : time unit
(note that I used a space between the two (could be optional if you want)
Using Java Pattern class to use that regex
Pattern p = Pattern.compile("(\\d+) (\\w+)");
Then you just have to iterate on each match to get the couple type/value
Matcher m = p.matcher(s);
while(m.find()){
String type = m.group(2);
int value = Integer.parseInt(m.group(1))
...
}
From that, just use a switch to convert the number into minute and add it to the variable, omitting the break to have a nice (but not efficient) converter :
switch(type){
//Add more time unit in the correct order if needed
case "days":
value *= 24;
case "hours":
value *= 60;
case "mins":
mins += value;
break;
}
Each type will convert the value into a correct number of minute, at the end, you will have the result in minutes.
Problem: There are few concerns as you never know without putting extra conditions like:
15 hours and 15 mins both will be stored in same integer value , you eventually need to differentiate them on some conditions to cater all the issues.
Coming to the question, you may achieve all this by using String split cases but you need to manually cater all the cases keeping in mind a user can use any spell words like hours can be hrs and so on
You could split the String at the whitespace and use the values in the array.
String value1 = "6 hours 43 mins";
String value2 = "15 mins";
String[] resultList1 = value1.split(" ");
String[] resultList2 = value2.split(" ");
int minutes1 = 0;
int minutes2 = 0;
if(resultList1.length == 4) {
minutes1 = Integer.parseInt(resultList1[0]) * 60 + Integer.parseInt(resultList1[2]);
} else {
minutes1 = Integer.parseInt(resultList1[0]);
}
if(resultList2.length == 4) {
minutes2 = Integer.parseInt(resultList2[0]) * 60 + Integer.parseInt(resultList2[2]);
} else {
minutes2 = Integer.parseInt(resultList2[0]);
}
System.out.println(minutes1);
System.out.println(minutes2);
The result is:
403
15
Either String split() or Pattern Matcher, as earlier answers suggest, will work. I'm not sure which will be more efficient though, but it's probably irrelevant in this case. My version:
String timeStr = "2 hours 15 mins";
String[] parts = timeStr.split(" ");
int totalMins = 0;
for(int i=1; i< parts.length; i+=2) {
// Add checking for "days", etc., if necessary.
if(parts[i].equals("hours")) {
int h = Integer.parseInt(parts[i-1]);
totalMins += 60 * h;
} else if(parts[i].equals("mins")) {
int m = Integer.parseInt(parts[i-1]);
totalMins += m;
}
}
System.out.println("totalMins = " + totalMins);
>> totalMins = 135
If you can get each minute and hours separately you can use string.replace("mins", "") then use Integer.parseInt().
If you get overral like 6 hours 43 mins you must split the string.
I am not sure whether this can be done in a single regex, but if I were you I would use a different regex to find the number of hours, the number of minutes, the number of seconds, etc.
Given a string in the format you mentioned, you can first extract the number of hours by using this regex:
\d+(?= hours?)
Then extract the number of minutes:
\d+(?= mins?)
If seconds can appear in the input string, you can use this to extract seconds as well:
\d+(?= secs?)
If any of the regexes don't match, that means there isn't that information in the string.
String time = "6 hours 43 mins";//or (43 mins) or (6 hours)
int h, m;
String[] parts = time.split(" ");
if (parts.length == 4) {
h = parts[1];
m = parts[3];
} else if (parts.length == 2) {
if (parts[1].isEqualTo("hours") {
h = parts[0];
} else if (parts[1].isEqualTo("mins") {
m = parts[0];
}
}
return h*60+m;

payUmoney integration is giving an error

After logging in, it's generating a hash value, but still giving error "Some problem occurred! try again".
PayUmoneySdkInitilizer.PaymentParam.Builder builder =
new PayUmoneySdkInitilizer.PaymentParam.Builder();
builder.setAmount(10.0)
.setTnxId("0nf7" + System.currentTimeMillis())
.setPhone(<My phone>)
.setProductName("product_name")
.setFirstName(<My Name>)
.setEmail(<My email>)
.setsUrl("https://www.payumoney.com/mobileapp/payumoney/success.php")
.setfUrl("https://www.payumoney.com/mobileapp/payumoney/failure.php")
.setUdf1("").setUdf2("").setUdf3("").setUdf4("").setUdf5("")
.setIsDebug(false)
.setKey(<mykey>)
.setMerchantId(<my debug merchant id>);
String tnxId="0nf7" + System.currentTimeMillis();
PayUmoneySdkInitilizer.PaymentParam paymentParam = builder.build();
String hashSequence = "<...>|"+tnxId+"|10.0|product_name|<My name>|<My email>|||||||||||salt";
String serverCalculatedHash= hashCal("SHA-512", hashSequence);
Toast.makeText(getApplicationContext(),
serverCalculatedHash, Toast.LENGTH_SHORT).show();
paymentParam.setMerchantHash(serverCalculatedHash);
// calculateServerSideHashAndInitiatePayment(paymentParam);
PayUmoneySdkInitilizer.startPaymentActivityForResult(TrayActivity.this, paymentParam);
public static String hashCal(String type, String str) {
byte[] hashseq = str.getBytes();
StringBuffer hexString = new StringBuffer();
try {
MessageDigest algorithm = MessageDigest.getInstance(type);
algorithm.reset();
algorithm.update(hashseq);
byte messageDigest[] = algorithm.digest();
for (int i = 0; i<messageDigest.length; i++) {
String hex = Integer.toHexString(0xFF &messageDigest[i]);
if (hex.length() == 1) { hexString.append("0"); }
hexString.append(hex);
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} return hexString.toString();
}
You use in the code:
.setTnxId("0nf7" + System.currentTimeMillis())
And then later:
String tnxId="0nf7" + System.currentTimeMillis();
Probably not the only problem, but do you really want to use two different values for these (the time may change between the two calls)? Didn't you want the same tnxId in both cases?
TransactionIdProvider.java:
import java.util.Locale;
public class TransactionIdProvider {
private final static String DEFAULT_PREFIX = "ID";
// Convenient prime number for incrementing the counter
private final static long ID_ADD = 0xF0AD; // "f*ck off and die"
// 64b counter with non-trivial start value
private static long idCounter = 0x0101F00DDEADBEEFL;
/**
* Returns ID consisting of prefix string and 64b counter interleaved
* with 32b per-4s-timestamp.
*
* May produce identical ID (collision) when:
* 1) class is reloaded within 4s
* (to fix: serialize "idCounter" upon shutdown/restart of VM, or
* modify prefix per start of VM)
* 2) more than 2^64 IDs are requested within 4s (no fix, unexpected)
* 3) more than 2^64 IDs are requested after cca. 550 years.
* (no fix, unexpected)
* 4) more than one static instance of TransactionIdProvider is used
* (two or more VMs running the app) (to fix put different prefix in
* every VM/server running this)
*
* Length of returned ID is prefix.length() + 24 alphanumeric symbols.
*/
public static synchronized String getNewId(final String prefix) {
idCounter += ID_ADD; // increment counter
// get 32b timestamp per ~4s (millis/4096) (good for ~550 years)
final int timeStamp = (int)(System.currentTimeMillis()>>12);
final int idPart1 = (int)(idCounter>>32);
final int idPart2 = (int)(idCounter);
return String.format(Locale.US, "%s%08X%08X%08X",
prefix, idPart1, timeStamp, idPart2);
}
public static String getNewId() {
return getNewId(DEFAULT_PREFIX);
}
}
Not sure how much usable is this one, and if the ID may be so long. Feel free to use/modify it any way you wish.
Also I wonder, whether I didn't forget about something important, but can't recall anything.
The security aspect of this one is still quite weak, as within 4s time span the ID will be like simple addition, but at least it's not producing 1, 2, 3... series.
Did found some SDK docs, looks like txnId may be 25 chars long, so you have 1 char for prefix only. Or cut down on timestamp, using %07X in format and masking value with 0x0FFFFFFF, that would make it repeat every ~34 years -> 2 letters for prefix. Or change counter to 32b int, should be still more than enough, unless you expect thousands of transactions per second -> that would remove 8 chars. Or base32/base64 the whole ID to shorten it (depends what alphabet is legal for content)...
Or whatever... already spent enough time with this. Hire a pro.

while loop not stopping when criteria is met

I am trying to do a snowball calculation for debt - for those who don't know - you make minimum payments on all loans from month to month. Once one is paid off, you take that minimum payment and add it to the next one - so on and so forth. I have each of my debt amounts on do while loops, but my screen turns black and I believe it's on an infinite loop. I have 10 total of these, but here are a few just to show how it's working:
int tempTimeTaken=0;
double newPmt = payment1 + aAmt;
while(amount1>0){
amount1 = (amount1 * rate1) - newPmt;
tempTimeTaken++;
}
newPmt = newPmt + payment2;
for (int i=0;i<tempTimeTaken;i++)
{
if(amount2>0){
amount2 = (amount2 * rate2) - payment2;
}
}
do{
if (amount2>0){
amount2 = (amount2 * rate2) - newPmt;
tempTimeTaken++;}
}while(amount2>0);
Each of the variables not initialized here are retrieved from a sharedpreference earlier in the activity. Once received, it's parsed in to a double (assuming it's not null).
try
{
amount2 = Double.parseDouble(debtAmount2);
}
catch ( Exception e )
{
amount2 = 0;
}
I've also tried the loops as
while (amount>0){
//do stuff
}
and that didn't work either - same effect.
Any suggestions on how to get this not to loop forever?
all data types are double (except tempTimeTaken is int) - initial values vary - they are input in a different activity and carried to this one via sharedpref with a default of 0
Generally the format of while loop is
while(check condition against loop counter){
//do your things
increment/ decrement loop counter
}
in your loop
while(amount1>0){
amount1 = (amount1 * rate1) - newPmt;
tempTimeTaken++;
}
you are assigning new value to loop counter amount1 and increment a tempTimeTaken. Print the value of amount1 in this loop check whether it gets negative at some point of time eg.
while(amount1>0){
amount1 = (amount1 * rate1) - newPmt;
Log.d("loop","Value of amount1 :"+amount1);
tempTimeTaken++;
}

Categories

Resources