i know how to get free capacity on internal memory and on external storage.
But i want to know max capacity of internal memory and max capacity of external storage, but i can't find any info about it on google
it is possible to achieve it?
thanks
Some new methods were introduced in API 18. This is the code I used to get total storage (internal + external).
private static final long KILOBYTE = 1024;
StatFs internalStatFs = new StatFs( Environment.getRootDirectory().getAbsolutePath() );
long internalTotal;
long internalFree;
StatFs externalStatFs = new StatFs( Environment.getExternalStorageDirectory().getAbsolutePath() );
long externalTotal;
long externalFree;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
internalTotal = ( internalStatFs.getBlockCountLong() * internalStatFs.getBlockSizeLong() ) / ( KILOBYTE * KILOBYTE );
internalFree = ( internalStatFs.getAvailableBlocksLong() * internalStatFs.getBlockSizeLong() ) / ( KILOBYTE * KILOBYTE );
externalTotal = ( externalStatFs.getBlockCountLong() * externalStatFs.getBlockSizeLong() ) / ( KILOBYTE * KILOBYTE );
externalFree = ( externalStatFs.getAvailableBlocksLong() * externalStatFs.getBlockSizeLong() ) / ( KILOBYTE * KILOBYTE );
}
else {
internalTotal = ( (long) internalStatFs.getBlockCount() * (long) internalStatFs.getBlockSize() ) / ( KILOBYTE * KILOBYTE );
internalFree = ( (long) internalStatFs.getAvailableBlocks() * (long) internalStatFs.getBlockSize() ) / ( KILOBYTE * KILOBYTE );
externalTotal = ( (long) externalStatFs.getBlockCount() * (long) externalStatFs.getBlockSize() ) / ( KILOBYTE * KILOBYTE );
externalFree = ( (long) externalStatFs.getAvailableBlocks() * (long) externalStatFs.getBlockSize() ) / ( KILOBYTE * KILOBYTE );
}
long total = internalTotal + externalTotal;
long free = internalFree + externalFree;
long used = total - free;
StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
long bytesAvailable = (long)stat.getBlockSize() * (long)stat.getBlockCount();
long megAvailable = bytesAvailable / 1048576;
Source
Also, use this for internal size.
StatFs stat = new StatFs(Environment.getDataDirectory().getPath());
This method will not work on all phones, most phones return the total amount of memory available to the user, less system memory. you might try using the 'df -h' linux command in a c++ method using the NDK, but some phone make that a system (su) command only. So the long and short of it is you can't.
StatFs - Retrieve overall information about the space on a filesystem. This is a wrapper for Unix statvfs().
From API level 18 we use
long getTotalBytes - The total number of bytes supported by the file system.
For older API use
int getBlockCount ()
int getBlockSize ()
StatFs stat = new StatFs(**path**);
long bytesAvailable = (long)stat.getBlockSize() *(long)stat.getBlockCount();
As path You use Environment.getExternalStorageDirectory(), please review this value. In devices with multiple shared/external storage directories, this directory represents the primary storage that the user will interact with.
You need use string values of path like this:
"/mnt/external_sd/"
"/mnt/extSdCard/"
You can retreive list of all /mnt/ devices and use one of this values.
File allMounted = new File("/mnt/");
if(allMounted.isDirectory()){
String[] dirs = allMounted.list();...}
or something like
var myfile=new Java.IO.File("storage/");
var listOfStorages=myfile.ListFiles();
or
String[] externals = System.getenv("SECONDARY_STORAGE").split(":");
Related
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
I'm comparing the new NetworkStats class with TrafficStats for measuring traffic for the network interfaces and a given application (pex Chrome)
Since TrafficStats has values since device boot the test that I'm performing is this:
Reboot phone.
Open Chrome.
Download 10 mb data (over WiFi).
The data obtained with TrafficStats is this:
TrafficStats.getTotalRxBytes() aprox 17.21 MB
TrafficStats.getUidRxBytes(chromeUid) aprox 13.22 MB
I grant the permission to NetworkStats and the values that I obtain are this:
wifiBucket.getRxBytes() + mobileBucket.getRxBytes() aprox 17.23 MB
dataFromWiFiBucket[1] + dataFromMobileBucket[1] gives 0 bytes
The code to obtain the data from NetworkStats is the following:
long timeStamp = System.currentTimeMillis();
long bootTime = System.currentTimeMillis() - SystemClock.elapsedRealtime();
NetworkStats.Bucket wifiBucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_WIFI, null, bootTime, timeStamp);
NetworkStats.Bucket mobileBucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_MOBILE, subscriberID, bootTime, timeStamp);
NetworkStats wifiBucketForApp = networkStatsManager.queryDetailsForUid(ConnectivityManager.TYPE_WIFI, null, bootTime, timeStamp, chromeUid);
NetworkStats mobileBucketForApp = networkStatsManager.queryDetailsForUid(ConnectivityManager.TYPE_MOBILE, subscriberID, bootTime, timeStamp, chromeUid);
long[] dataFromWiFiBucket = getDataFromBucket(wifiBucketForApp);
long[] dataFromMobileBucket = getDataFromBucket(mobileBucketForApp);
Where getDataFromBucket is:
#RequiresApi(api = Build.VERSION_CODES.M) public static long[] getDataFromBucket(NetworkStats bucketForApp) {
long dataTx = 0;
long dataRx = 0;
NetworkStats.Bucket bucket;
while (bucketForApp.hasNextBucket()) {
bucket = new NetworkStats.Bucket();
bucketForApp.getNextBucket(bucket);
dataTx += bucket.getTxBytes();
dataRx += bucket.getRxBytes();
}
return new long[]{dataTx, dataRx};
}
I've read somewhere that buckets are from two hours so I've added this code:
if (bootTime > (timeStamp - TimeUnit.HOURS.toMillis(TWO_HOURS))) {
bootTime = timeStamp - TimeUnit.HOURS.toMillis(TWO_HOURS);
}
But data for chrome is still 0 because wifiBucketForApp and mobileBucketForApp do not have any buckets.
If I set bootTime to the beginning of the day (its 18:30 in my country) I obtain:
wifiBucket.getRxBytes() + mobileBucket.getRxBytes() aprox 44.74 MB (expected because is since the beginning of the day)
dataFromWiFiBucket[1] + dataFromMobileBucket[1] gives 26.32 MB
Does anybody know why I'm not obtaining the same values as TrafficStats since device boot from NetworkStatsManager for the Chrome app?
Since it's not your own app's traffic you need to allow manually Usage data access in the device settings.
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.
This code return total internal memory size:
public static String getTotalInternalMemorySize() {
File path = Environment.getDataDirectory();
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long totalBlocks = stat.getBlockCount();
return formatSize(totalBlocks * blockSize);
}
But this size is without system used memory.
For example, at the GALAXY NOTE 3 is the total internal memory of 32 GB, but this function returns only 26.18 GB.
How to determine the overall internal memory including missing 5.82 GB of system memory?
The basic idea that may work is to compute the first number which is power of two, and it is bigger than the number you got returned from the function.
Ex: 2^5 = 32 > 26
In this case your number is 32. You should convert to integer before comparing obviously.
I have the following memory details from the DDMS perspective of Eclipse.
However in spite of implementing the following code, I'm unable to obtain the values shown in the above image.
private void logHeap() {
long maxMemory = Runtime.getRuntime().maxMemory()/ (1024*1024);
long totalMemory = Runtime.getRuntime().totalMemory() / (1024*1024);
long heapSize = Debug.getNativeHeapSize()/(1024*1024);
long allocatedHeapSize = Debug.getNativeHeapAllocatedSize() / (1024*1024);
long freeHeapSize = Debug.getNativeHeapFreeSize() / (1024*1024);
DecimalFormat df = new DecimalFormat();
df.setMaximumFractionDigits(2);
df.setMinimumFractionDigits(2);
Log.d(TAG, "debug. =================================");
Log.d(TAG,"Max memory: "+df.format(maxMemory)+" MB");
Log.d(TAG,"Total memory: "+df.format(totalMemory)+" MB");
Log.d(TAG,"Heap Size: "+df.format(heapSize)+" MB");
Log.d(TAG,"Allocated Heapsize: "+df.format(allocatedHeapSize)+" MB");
Log.d(TAG,"Free Heapsize: "+df.format(freeHeapSize)+" MB");
}
I'm getting the following values:
Max Memory : 36.00MB
Total Memory : 7.00 MB
Heap Size : 3.00 MB
allocated heapsize : 3.00 MB
free heapsize : 0.00 MB
Are there any other APIs to obtain the details?