[Q][SOLVED]Get path and size of SDcard in Android 4.4 KitKat - Java for Android App Development

Hello everyone, I have an app on Google Play that shows the end user information about their device. Within this information, a Memory/Storage category is shown. Everything was good and fine until mean ol` KitKat wanted to deny access to the SDcard... Although I can understand Google's move on that subject, it can not go un-noticed that it may break many app's functionality (like my own). Anyhow, below is my class that scans for mount points, and stores them in an ArrayList. I used some code from StackOverflow somewhere, but I do not have the link.
StorageUtils :
Code:
public class StorageUtils {
private static final String TAG = "StorageUtils";
public static class StorageInfo {
public final String path;
public final boolean internal;
public final boolean readonly;
public final int display_number;
StorageInfo(String path, boolean internal, boolean readonly,
int display_number) {
this.path = path;
this.internal = internal;
this.readonly = readonly;
this.display_number = display_number;
}
}
public static ArrayList<StorageInfo> getStorageList() {
ArrayList<StorageInfo> list = new ArrayList<StorageInfo>();
String def_path = Environment.getExternalStorageDirectory().getPath();
boolean def_path_internal = !Environment.isExternalStorageRemovable();
String def_path_state = Environment.getExternalStorageState();
boolean def_path_available = def_path_state
.equals(Environment.MEDIA_MOUNTED)
|| def_path_state.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
boolean def_path_readonly = Environment.getExternalStorageState()
.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
BufferedReader buf_reader = null;
try {
HashSet<String> paths = new HashSet<String>();
buf_reader = new BufferedReader(new FileReader("/proc/mounts"));
String line;
int cur_display_number = 1;
Log.d(TAG, "/proc/mounts");
while ((line = buf_reader.readLine()) != null) {
Log.d(TAG, line);
if (line.contains("vfat") || line.contains("/mnt")) {
StringTokenizer tokens = new StringTokenizer(line, " ");
String unused = tokens.nextToken(); // device
String mount_point = tokens.nextToken(); // mount point
if (paths.contains(mount_point)) {
continue;
}
unused = tokens.nextToken(); // file system
List<String> flags = Arrays.asList(tokens.nextToken()
.split(",")); // flags
boolean readonly = flags.contains("ro");
if (mount_point.equals(def_path)) {
paths.add(def_path);
list.add(new StorageInfo(def_path, def_path_internal,
readonly, -1));
} else if (line.contains("/dev/block/vold")) {
if (!line.contains("/mnt/secure")
&& !line.contains("/mnt/asec")
&& !line.contains("/mnt/obb")
&& !line.contains("/dev/mapper")
&& !line.contains("tmpfs")) {
paths.add(mount_point);
list.add(new StorageInfo(mount_point, false,
readonly, cur_display_number++));
}
}
}
}
if (!paths.contains(def_path) && def_path_available) {
list.add(new StorageInfo(def_path, def_path_internal,
def_path_readonly, -1));
}
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (buf_reader != null) {
try {
buf_reader.close();
} catch (IOException ex) {
}
}
}
return list;
}
public static String getReadableFileSize(long bytes, boolean si) {
int unit = si ? 1000 : 1024;
if (bytes < unit)
return bytes + " B";
int exp = (int) (Math.log(bytes) / Math.log(unit));
String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1)
+ (si ? "" : "i");
return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
}
@SuppressLint("NewApi")
public static long getFreeSpace(String path) {
StatFs statFs = new StatFs(path);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
long sdAvailSize = statFs.getFreeBlocksLong()
* statFs.getBlockSizeLong();
return sdAvailSize;
} else {
@SuppressWarnings("deprecation")
double sdAvailSize = (double) statFs.getFreeBlocks()
* (double) statFs.getBlockSize();
return (long) sdAvailSize;
}
}
public static long getUsedSpace(String path) {
return getTotalSpace(path) - getFreeSpace(path);
}
@SuppressLint("NewApi")
public static long getTotalSpace(String path) {
StatFs statFs = new StatFs(path);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
long sdTotalSize = statFs.getBlockCountLong()
* statFs.getBlockSizeLong();
return sdTotalSize;
} else {
@SuppressWarnings("deprecation")
double sdTotalSize = (double) statFs.getBlockCount()
* statFs.getBlockSize();
return (long) sdTotalSize;
}
}
/**
* getSize()[0] is /mnt/sdcard. getSize()[1] is size of sd (example 12.0G),
* getSize()[2] is used, [3] is free, [4] is blksize
*
* @return
* @throws IOException
*/
public static String[] getSize() throws IOException {
String memory = "";
Process p = Runtime.getRuntime().exec("df /mnt/sdcard");
InputStream is = p.getInputStream();
int by = -1;
while ((by = is.read()) != -1) {
memory += new String(new byte[] { (byte) by });
}
for (String df : memory.split("/n")) {
if (df.startsWith("/mnt/sdcard")) {
String[] par = df.split(" ");
List<String> pp = new ArrayList<String>();
for (String pa : par) {
if (!pa.isEmpty()) {
pp.add(pa);
}
}
return pp.toArray(new String[pp.size()]);
}
}
return null;
}
}
Next, I retrieve the used, free, and total space of each mount point. This is where KitKat breaks my app.
CpuMemFragment :
Code:
public class CpuMemFragment extends Fragment {
// CPU
String devCpuInfo;
TextView tvCpuInfo;
// RAM
String devRamInfo;
TextView tvRamInfo;
// Storage
String devStorageA, devStorageB;
TextView tvStorageAName, tvStorageA, tvStorageB, tvStorageBName;
AdView adView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.cpu_mem, container, false);
return rootView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
// *** CPU ***
//
devCpuInfo = readCpuInfo();
//
// #################################
// *** RAM ***
//
devRamInfo = readTotalRam();
//
// #################################
// *** STORAGE ***
//
ArrayList<StorageInfo> storageInfoList = StorageUtils.getStorageList();
tvStorageAName = (TextView) getView().findViewById(R.id.tvStorageAName);
tvStorageBName = (TextView) getView().findViewById(R.id.tvStorageBName);
if (storageInfoList.size() > 0) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
&& !storageInfoList.get(0).internal) {
kitKatWorkaround(0);
}
tvStorageAName.setText(storageInfoList.get(0).path);
devStorageA = StorageUtils.getReadableFileSize(
(StorageUtils.getUsedSpace(storageInfoList.get(0).path)),
true)
+ "/"
+ StorageUtils.getReadableFileSize((StorageUtils
.getTotalSpace(storageInfoList.get(0).path)), true);
if (storageInfoList.size() > 1) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
&& !storageInfoList.get(0).internal) {
kitKatWorkaround(1);
}
tvStorageBName.setText(storageInfoList.get(1).path);
devStorageB = StorageUtils.getReadableFileSize(
StorageUtils.getUsedSpace(storageInfoList.get(1).path)
+ (StorageUtils.getUsedSpace("system/")), true)
+ "/"
+ StorageUtils.getReadableFileSize((StorageUtils
.getTotalSpace(storageInfoList.get(1).path)),
true);
} else {
devStorageB = "N/A";
}
} else {
devStorageA = "N/A";
devStorageB = "N/A";
}
//
// #################################
// CPU
tvCpuInfo = (TextView) getView().findViewById(R.id.tvCpuInfo);
tvCpuInfo.setText(devCpuInfo);
//
// #################################
// RAM
tvRamInfo = (TextView) getView().findViewById(R.id.tvRamInfo);
tvRamInfo.setText(devRamInfo);
//
// #################################
// STORAGE
tvStorageA = (TextView) getView().findViewById(R.id.tvStorageA);
tvStorageA.setText(devStorageA);
tvStorageB = (TextView) getView().findViewById(R.id.tvStorageB);
tvStorageB.setText(devStorageB);
//
// #################################
// Look up the AdView as a resource and load a request.
adView = (AdView) getActivity().findViewById(R.id.adCpuMemBanner);
AdRequest adRequest = new AdRequest.Builder().build();
adView.loadAd(adRequest);
}
@Override
public void onPause() {
if (adView != null) {
adView.pause();
}
super.onPause();
}
@Override
public void onResume() {
super.onResume();
if (adView != null) {
adView.resume();
}
}
@Override
public void onDestroy() {
if (adView != null) {
adView.destroy();
}
super.onDestroy();
}
private static synchronized String readCpuInfo() {
ProcessBuilder cmd;
String result = "";
try {
String[] args = { "/system/bin/cat", "/proc/cpuinfo" };
cmd = new ProcessBuilder(args);
Process process = cmd.start();
InputStream in = process.getInputStream();
byte[] re = new byte[1024];
while (in.read(re) != -1) {
System.out.println(new String(re));
result = result + new String(re);
}
in.close();
} catch (IOException ex) {
ex.printStackTrace();
}
return result;
}
public static synchronized String readTotalRam() {
String load = "";
try {
RandomAccessFile reader = new RandomAccessFile("/proc/meminfo", "r");
load = reader.readLine();
reader.close();
} catch (IOException ex) {
ex.printStackTrace();
}
return load;
}
// An attempt to workaround KitKat changes according to android documentation
public void kitKatWorkaround(int index) {
String path1 = Environment.getExternalStorageDirectory().getPath();
if (index == 0) {
tvStorageAName.setText(path1);
devStorageA = StorageUtils.getReadableFileSize(
(StorageUtils.getUsedSpace(path1)), true)
+ "/"
+ StorageUtils.getReadableFileSize(
(StorageUtils.getTotalSpace(path1)), true);
}
if (index == 1) {
tvStorageBName.setText(path1);
devStorageB = StorageUtils.getReadableFileSize(
StorageUtils.getUsedSpace(path1)
+ (StorageUtils.getUsedSpace("system/")), true)
+ "/"
+ StorageUtils.getReadableFileSize(
(StorageUtils.getTotalSpace(path1)), true);
}
}
}
The suspected error is right here in the logcat:
Caused by: libcore.io.ErrnoException: statvfs failed: EACCES (Permission denied)
Click to expand...
Click to collapse
is there any alternative to retrieving sdCards sizes, or should I simply display a dialog stating that I have no control over Google's decision in Android 4.4, and apologize for the inconvenince?
Also, while I'm at it: On some models of Android devices, the sizes of the SDcard are all out of whack. Some showing more used space than total, and innacurate readings. This seems to only happen with internal/emulated storage. What is the most accurate way of getting sizes of all SDcard locations?
Thank you kindly for your time, Happy Coding!

Fully Functional
Got it working after further looking into android documentation, and implementing new methods:
Within analyzing storage method:
Code:
...
ArrayList<StorageInfo> storageInfoList = StorageUtils.getStorageList();
tvStorageAName = (TextView) getView().findViewById(R.id.tvStorageAName);
tvStorageBName = (TextView) getView().findViewById(R.id.tvStorageBName);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
kitKatWorkaround();
} else if (storageInfoList.size() > 0) {
tvStorageAName.setText(storageInfoList.get(0).path);
devStorageA = StorageUtils.getReadableFileSize(
(StorageUtils.getUsedSpace(storageInfoList.get(0).path)),
true)
+ "/"
+ StorageUtils.getReadableFileSize((StorageUtils
.getTotalSpace(storageInfoList.get(0).path)), true);
if (storageInfoList.size() > 1) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
&& !storageInfoList.get(0).internal) {
kitKatWorkaround();
}
tvStorageBName.setText(storageInfoList.get(1).path);
devStorageB = StorageUtils.getReadableFileSize(
StorageUtils.getUsedSpace(storageInfoList.get(1).path)
+ (StorageUtils.getUsedSpace("system/")), true)
+ "/"
+ StorageUtils.getReadableFileSize((StorageUtils
.getTotalSpace(storageInfoList.get(1).path)),
true);
} else {
devStorageB = "N/A";
}
} else {
devStorageA = "N/A";
devStorageB = "N/A";
}
...
kitKatWorkaround();
Code:
@SuppressLint("NewApi")
public void kitKatWorkaround() {
tvStorageA = (TextView) getView().findViewById(R.id.tvStorageA);
tvStorageB = (TextView) getView().findViewById(R.id.tvStorageB);
File[] sdCards = getActivity().getApplicationContext()
.getExternalCacheDirs();
if (sdCards.length > 0) {
File sdCard1 = sdCards[0];
tvStorageAName.setText(sdCard1.getAbsolutePath()
.replace(
"Android/data/" + getActivity().getPackageName()
+ "/cache", ""));
devStorageA = StorageUtils.getReadableFileSize(
(StorageUtils.getUsedSpace(sdCard1.getAbsolutePath())),
true)
+ "/"
+ StorageUtils.getReadableFileSize((StorageUtils
.getTotalSpace(sdCard1.getAbsolutePath())), true);
if (sdCards.length > 1) {
File sdCard2 = sdCards[1];
tvStorageBName.setText(sdCard2.getAbsolutePath().replace(
"Android/data/" + getActivity().getPackageName()
+ "/cache", ""));
devStorageB = StorageUtils.getReadableFileSize(
(StorageUtils.getUsedSpace(sdCard2.getAbsolutePath())),
true)
+ "/"
+ StorageUtils.getReadableFileSize((StorageUtils
.getTotalSpace(sdCard2.getAbsolutePath())),
true);
} else {
devStorageB = "N/A";
}
} else {
devStorageA = "N/A";
devStorageB = "N/A";
}
tvStorageA.setText(devStorageA);
tvStorageB.setText(devStorageB);
}
Just going to leave this out there, it works on at least Android 3.0+ that I have tested. Using StorageUtils retrieve all available mount points, and use code above to setText() path and size
Feel free to use this if it helps (don't forget the thanks button) :good:

Related

Retrieving cpu frequency

Hi everyone.
I want to retrieve the current cpu frequency in my app but I don't seem to be right.
In my code I want to read the "scaling_cpu_freq" file from internal storage.
This is the code:
Code:
private String ReadCPUMhz() {
String cpuMaxFreq = "";
int cur = 0;
try {
[user=1299008]@supp[/user]ressWarnings("resource")
BufferedReader maxi = new BufferedReader(new FileReader(new File("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq")));
try{
cpuMaxFreq = maxi.readLine();
cur = Integer.parseInt(cpuMaxFreq);
cur = cur/1000;
} catch (Exception ex){
ex.printStackTrace();
}
} catch (FileNotFoundException f) {
f.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return String.valueOf(cur);
}
The problem is that the method only returns 0, which is the initial value of the int "cur".
Can anybody help me?
Thanks in advance.
Here's the code I use:
Declare this class in your Activity
Code:
// Read current frequency from /sys in a separate thread
// This class assumes your TextView is declared and referenced in the OnCreate of the class this one is declared in
// And its variable name is mCurCpuFreq
protected class CurCPUThread extends Thread {
private static final String CURRENT_CPU = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq";
private boolean mInterrupt = false;
public void interrupt() {
mInterrupt = true;
}
[user=439709]@override[/user]
public void run() {
try {
while (!mInterrupt) {
sleep(400);
final String curFreq = readOneLine(CURRENT_CPU);
mCurCPUHandler.sendMessage(mCurCPUHandler.obtainMessage(0,
curFreq));
}
} catch (InterruptedException e) {
return;
}
}
}
// Update real-time current frequency & stats in a separate thread
protected static Handler mCurCPUHandler = new Handler() {
public void handleMessage(Message msg) {
mCurFreq.setText(toMHz((String) msg.obj));
final int p = Integer.parseInt((String) msg.obj);
new Thread(new Runnable() {
public void run() {
// Here I update a real-time graph of the current freq
}
}
}).start();
}
};
Helper methods used :
Code:
// Convert raw collected values to formatted MhZ
private static String toMHz(String mhzString) {
if (Integer.valueOf(mhzString) != null)
return String.valueOf(Integer.valueOf(mhzString) / 1000) + " MHz";
else
return "NaN";
}
// Iterate through the /sys file
public static String readOneLine(String fname) {
BufferedReader br;
String line = null;
try {
br = new BufferedReader(new FileReader(fname), 512);
try {
line = br.readLine();
} finally {
br.close();
}
} catch (Exception e) {
Log.e(TAG, "IO Exception when reading sys file", e);
// attempt to do magic!
return readFileViaShell(fname, true);
}
return line;
}
// Backup method if the above one fails
public static String readFileViaShell(String filePath, boolean useSu) {
CommandResult cr = null;
if (useSu) {
cr = new CMDProcessor().runSuCommand("cat " + filePath);
} else {
cr = new CMDProcessor().runShellCommand("cat " + filePath);
}
if (cr.success())
return cr.getStdout();
return null;
}
CMDProcessor.java and its dependencies attached to this post

[Q] Selecting Text from a TextView for GingerBread

I would like to select text from a textview,partially that is for Gingerbread as well as higher platforms,I find that android:textIsSelectable is not available and the WebView workaround only does it for complete text,I have tried to use pre-baked code to do this by extending a TextView:
public class SelectableTextView extends TextView {
final String TAG="SelectableTextView";
public static int _SelectedBackgroundColor = 0xffA6D4E1;
public static int _SelectedTextColor = 0xff000000;
private OnTouchListener lastOnTouch;
protected int textOffsetStart;
protected int textOffsetEnd;
private OnLongClickListener lastOnLongClick;
protected boolean longCliked;
protected boolean isDowned;
protected int textSelectedEnd;
protected int textSelectedStart;
private static SelectableTextView lastInstance;
public SelectableTextView(Context context) {
super(context);
}
public SelectableTextView(Context context,AttributeSet attrs)
{
super(context,attrs);
}
public SelectableTextView(Context context,AttributeSet attrs,int defStyle)
{
super(context,attrs,defStyle);
}
@SuppressLint("NewApi")
public void setTextIsSelectable(boolean selectable) {
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB)
super.setTextIsSelectable(true);
else
{
super.setLongClickable(true);
super.setOnLongClickListener(getSelectableLongClick());
super.setOnTouchListener(getSelectableOnTouch());
}
}
private OnLongClickListener getSelectableLongClick() {
return new OnLongClickListener() {
@override
public boolean onLongClick(View v) {
longCliked = true;
if (lastOnLongClick != null) {
lastOnLongClick.onLongClick(v);
}
return true;
}
};
}
@override
public void setOnTouchListener(OnTouchListener listener) {
super.setOnTouchListener(listener);
this.lastOnTouch = listener;
}
@override
public void setOnLongClickListener(OnLongClickListener listener) {
super.setOnLongClickListener(listener);
Log.d(TAG, "Setting touch listener in long click");
this.lastOnLongClick = listener;
// this.setOnTouchListener(getSelectableOnTouch());
}
private OnTouchListener getSelectableOnTouch() {
return new OnTouchListener() {
@override
public boolean onTouch(View v, MotionEvent event) {
Log.d(TAG, "In SelectableTextView OnTouchListener");
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
Log.d(TAG, "Finger down on the TextView");
if (lastInstance == null)
lastInstance = SelectableTextView.this;
if (lastInstance != null && lastInstance != SelectableTextView.this) {
lastInstance.clean();
lastInstance = SelectableTextView.this;
}
int offset = getOffset(event);
Log.d(TAG, "Selection starts at: "+offset);
if ((offset < textOffsetEnd && offset > textOffsetStart)
|| (offset > textOffsetEnd && offset < textOffsetStart)) {
if (textOffsetEnd - offset > offset - textOffsetStart)
textOffsetStart = textOffsetEnd;
} else {
clean();
textOffsetStart = offset;
}
isDowned = true;
} else if (isDowned && longCliked && action == MotionEvent.ACTION_MOVE) {
Log.d(TAG, "Selecting text");
selectTextOnMove(event);
} else if (action == MotionEvent.ACTION_UP) {
isDowned = false;
longCliked = false;
}
if (lastOnTouch != null)
lastOnTouch.onTouch(v, event);
return false;
}
};
}
private void selectTextOnMove(MotionEvent event) {
Log.d(TAG, "Selection text on ACTION_MOVE");
int offset = getOffset(event);
if (offset != Integer.MIN_VALUE) {
String text = getText().toString();
SpannableStringBuilder sb = new SpannableStringBuilder(text);
BackgroundColorSpan bgc = new BackgroundColorSpan(_SelectedBackgroundColor);
ForegroundColorSpan textColor = new ForegroundColorSpan(_SelectedTextColor);
int start = textOffsetStart;
textOffsetEnd = offset;
int end = offset;
Log.d(TAG,"Start: "+start+"and End: "+end);
if (start > end) {
int temp = start;
start = end;
end = temp;
Log.d(TAG, "Interchanging Start: "+start+" and End: "+end);
}
int[] curectStartEnd = curectStartEnd(text, start, end);
start = curectStartEnd[0];
end = curectStartEnd[1];
Log.d(TAG, "Corrected start and end,Start: "+start+" and End: "+end+".These values are final");
SelectableTextView.this.textSelectedStart = start;
SelectableTextView.this.textSelectedEnd = end;
sb.setSpan(bgc, start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
sb.setSpan(textColor, start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
this.setText(sb);
}
}
private int[] curectStartEnd(String text, int start, int end) {
int length = text.length();
while (start < length && start > 0 && text.charAt(start) != ' ') {
start--;
}
while (end < length && text.charAt(end) != ' ') {
end++;
}
return new int[] { start, end };
}
private int getOffset(MotionEvent event) {
Log.d(TAG,"Get offset method");
Layout layout = getLayout();
if (layout == null)
return Integer.MIN_VALUE;
float x = event.getX() + getScrollX();
float y = event.getY() + getScrollY();
int line = layout.getLineForVertical((int) y);
Log.d(TAG, "Obtaining line "+line);
int offset = layout.getOffsetForHorizontal(line, x);
return offset;
}
protected void clean() {
String gotText=this.getText().toString();
if (gotText != null) {
this.setText(gotText);
textSelectedStart = 0;
textSelectedEnd = 0;
}
}
@override
public int getSelectionStart() {
return textSelectedStart;
}
@override
public int getSelectionEnd() {
return textSelectedEnd;
}
}
This is how I am using it:
txt_copyFrom.setClickable(false);
txt_copyFrom.setCursorVisible(true);
txt_copyFrom.setEnabled(true);
txt_copyFrom.setTextIsSelectable(true);
txt_copyFrom.setOnLongClickListener(new OnLongClickListener(){
@override
public boolean onLongClick(View v) {
Log.d(TAG, "On LongClick Listener");
int start=txt_copyFrom.getSelectionStart();
int end=txt_copyFrom.getSelectionEnd();
if(start>end)
{
//I guess the SelectableTextView fixes this:
start=start+end;
end=start=end;
start=start-end;
}
mSelectedText=txt_copyFrom.getText().toString().substring(start, end);
Log.d(TAG, "Selected text: "+mSelectedText);
return true;
}});
I get a StackOverflowError:
It repeatedly prints the message:
SelectableTextView(12712): In SelectableTextView OnTouchListener
SelectableTextView(12712): Finger down on the TextView
SelectableTextView(12712): Get offset method
SelectableTextView(12712): Obtaining line 4
SelectableTextView(12712): Selection starts at: 205
Followed by:
AndroidRuntime(12712): FATAL EXCEPTION: main
AndroidRuntime(12712): java.lang.StackOverflowError
AndroidRuntime(12712): at android.text.MeasuredText.addStyleRun(MeasuredText.java:164)
AndroidRuntime(12712): at android.text.MeasuredText.addStyleRun(MeasuredText.java:204)
at android.text.StaticLayout.generate(StaticLayout.java:281)
AndroidRuntime(12712): at android.text.DynamicLayout.reflow(DynamicLayout.java:284)
AndroidRuntime(12712): at android.text.DynamicLayout.<init>(DynamicLayout.java:170)
AndroidRuntime(12712): at android.widget.TextView.makeSingleLayout(TextView.java:6044)
AndroidRuntime(12712): at android.widget.TextView.makeNewLayout(TextView.java:5942)
AndroidRuntime(12712): at android.widget.TextView.checkForRelayout(TextView.java:6481)
AndroidRuntime(12712): at android.widget.TextView.setText(TextView.java:3764)
AndroidRuntime(12712): at android.widget.TextView.setText(TextView.java:3622)
AndroidRuntime(12712): at android.widget.TextView.setText(TextView.java:3597)
AndroidRuntime(12712): at com.example.clipboardtest.SelectableTextView.clean(SelectableTextView.java:185)
This happens to be:this.setText(this.getText().toString());
This is followed by:
AndroidRuntime(12712): at com.example.clipboardtest.SelectableTextView$2.onTouch(SelectableTextView.java:108)
This is,as expected: clean();
Then this occurs repeatedly:
AndroidRuntime(12712): at com.example.clipboardtest.SelectableTextView$2.onTouch(SelectableTextView.java:120)
which is `lastOnTouch.onTouch(v, event);`
I guess this is because we retain the OnLongClick and OnTouchListener.
Also the code calls for selection of stuff using a background colour and foreground color:
SpannableStringBuilder sb = new SpannableStringBuilder(text);
BackgroundColorSpan bgc = new BackgroundColorSpan(_SelectedBackgroundColor);
ForegroundColorSpan textColor = new ForegroundColorSpan(_SelectedTextColor);
sb.setSpan(bgc, start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
sb.setSpan(textColor, start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
setText(this);
I do not understand why this implementation does not chain to the superclass implementation like I specifically asked it to.Is there anything else I can do,any approach I can follow to make it work,is there a pre-implemented version I can use.If there is nothing can you guide me through implementing a custom TextView for Android

How can I loop through my JSON object?

I am new to Java and I am getting kind of stuck by trying to loop through my JSON. I am retrieving a JSON object where I want to loop through.
My JSON looks as follow:
Code:
{"message":{"2":[{"uid":"2","title":"","message":"Test1","success":1,"created_at":null,"updated_at":null}],"3":[{"uid":"3","title":"","message":"Test2 !","success":1,"created_at":null,"updated_at":null}],"4":[{"uid":"4","title":"Bla","message":"Test3!","success":1,"created_at":null,"updated_at":null}]}}
I tried a loop like this:
Code:
for(int i = 0; i<json.names().length(); i++){
try {
Log.v("TEST", "key = " + json.names().getString(i) + " value = " + json.get(json.names().getString(i)));
} catch (JSONException e) {
e.printStackTrace();
}
}
But this will only target "message" which includes the whole JSON "string". I want to loop through each message and retrieving the value of uid 1, uid 2 etc. How can I achieve this?
Thanks in advance.
Here is how I'm doing it:
Code:
private static final String AllNewsItemsURL = "some_url_here.php";
private static final String TAG_SUCCESS = "success";
private static final String NEWS = "news";
private static final String TITLE = "title";
private static final String STORY = "story";
private final JSONParser jParser = new JSONParser();
private JSONArray newsItems = null;
..... / code snipped / ....
try {
JSONObject json = jParser.makeHttpRequest(AllNewsItemsURL, params);
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
newsItems = json.getJSONArray(NEWS);
for (int i = 0; i < newsItems.length(); i++) {
JSONObject obj = newsItems.getJSONObject(i);
Integer id = i + 1;
String title = obj.getString(TITLE);
String story = obj.getString(STORY);
}
} else {
Log.e("JSON Response", "success == 0");
}
} catch (Exception e) {
e.printStackTrace();
}
Thanks for your reply. I tried it but getting this exception:
Code:
org.json.JSONException: Value {"2":[{"uid":"2","title":"","message":"Test1","success":1,"created_at":null,"updated_at":null}],"3":[{"uid":"3","title":"","message":"Test2","success":1,"created_at":null,"updated_at":null}],"4":[{"uid":"4","title":"Bla","message":"Test3","success":1,"created_at":null,"updated_at":null}]} at messages of type org.json.JSONObject cannot be converted to JSONArray
CodeMonkeyy said:
Thanks for your reply. I tried it but getting this exception:
Code:
org.json.JSONException: Value {"2":[{"uid":"2","title":"","message":"Test1","success":1,"created_at":null,"updated_at":null}],"3":[{"uid":"3","title":"","message":"Test2","success":1,"created_at":null,"updated_at":null}],"4":[{"uid":"4","title":"Bla","message":"Test3","success":1,"created_at":null,"updated_at":null}]} at messages of type org.json.JSONObject cannot be converted to JSONArray
Click to expand...
Click to collapse
You might want to try the matching JSONParser I have for it, sorry forgot to include it:
https://github.com/JonnyXDA/WGSB/bl...om/jonny/wgsb/material/parser/JSONParser.java
Also noting that your entire JSON Array is called "message" but you also have a parameter called "message" - maybe rename the Array to "messages"?
As for the code you should have something like:
Code:
private static final String AllNewsItemsURL = "some_url_here.php";
private static final String TAG_SUCCESS = "success";
private static final String MESSAGES = "messages";
private static final String TITLE = "title";
private static final String MESSAGE = "message";
private final JSONParser jParser = new JSONParser();
private JSONArray messageItems = null;
..... / code snipped / ....
try {
JSONObject json = jParser.makeHttpRequest(AllNewsItemsURL, params);
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
messageItems = json.getJSONArray(MESSAGES);
for (int i = 0; i < messageItems.length(); i++) {
JSONObject obj = messageItems.getJSONObject(i);
String title = obj.getString(TITLE);
String message = obj.getString(MESSAGE);
}
} else {
Log.e("JSON Response", "success == 0");
}
} catch (Exception e) {
e.printStackTrace();
}
My code looks like the this:
Code:
//Message task
MessageTask task = new MessageTask(DashboardActivity.class);
task.execute();
try {
json = task.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
try {
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
messageItems = json.getJSONArray(MESSAGES);
for (int i = 0; i < messageItems.length(); i++) {
JSONObject obj = messageItems.getJSONObject(i);
String title = obj.getString(TITLE);
String message = obj.getString(MESSAGE);
}
} else {
Log.e("JSON Response", "success == 0");
}
} catch (Exception e) {
e.printStackTrace();
}
I am using Async Task to retrieve my JSON.
And my JSON parser looks like this:
Code:
public class JSONParser {
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
// constructor
public JSONParser() {
}
public JSONObject getJSONFromUrl(String url, List<NameValuePair> params) {
// Making HTTP request
try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(params));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
json = sb.toString();
Log.e("JSON", json);
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
// try parse the string to a JSON object
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
// return JSON String
return jObj;
}
}
But it doesn't get through the if statement, because it can't find the value success. ( org.json.JSONException: No value for success ). Don't really know what I am doing wrong here. Is it because I am using AsyncTask and retrieving my JSON the wrong way?
I also renamed my Array to "messages", stupid mistake thanks!
CodeMonkeyy said:
But it doesn't get through the if statement, because it can't find the value success. ( org.json.JSONException: No value for success ). Don't really know what I am doing wrong here. Is it because I am using AsyncTask and retrieving my JSON the wrong way?
I also renamed my Array to "messages", stupid mistake thanks!
Click to expand...
Click to collapse
We're getting closer! With regards to using AsyncTask - thats fine and the recommended way to do service side sync/download operations (doesn't block the UI thread) so no need to change that.
I just took a look at my reference JSON and I have the success tag outside of an item eg:
Code:
{"topical":[{"tid":"5","title":"Exam countdown... just 12 weeks left!","story":"some_story_text_here","staff":"0","red":"0","show":"1"}],[COLOR="red"]"success":1[/COLOR]}
Whereas your success tag is put in each item:
Code:
{"message":{"2":[{"uid":"2","title":"","message":"Test1","[COLOR="red"]success":1,[/COLOR]"created_at":null,"updated_at":null}],"3":[{"uid":"3","title":"","message":"Test2 !",[COLOR="red"]"success":1[/COLOR],"created_at":null,"updated_at":null}],"4":[{"uid":"4","title":"Bla","message":"Test3!","[COLOR="Red"]success":1[/COLOR],"created_at":null,"updated_at":null}]}}
I'm guessing that your php line for:
PHP:
$response["success"] = 1;
is inside of the while loop:
PHP:
while ($row = mysql_fetch_array($result)) {
Taking it out of the while loop should fix that
That makes sense, because I am trying to get a success code for my whole JSON response. I changed my PHP code to:
Code:
while($row = mysqli_fetch_array( $messages )) {
// create rowArr
$rowArr = array(
'uid' => $row['id'],
'title' => $row['title'],
'message' => $row["message"],
'created_at' => $row['created_at'],
'updated_at' => $row['updated_at'],
);
// store rowArr in $return_arr
$return_arr[$row['id']][] = $rowArr;
}
$return_arr['success'] = 1;
// Json encode
echo json_encode(array("messages" => $return_arr));
}
Retrieving the following JSON:
Code:
{"messages":{"2":[{"uid":"2","title":"","message":"Test1","created_at":null,"updated_at":null}],"3":[{"uid":"3","title":"","message":"Test2 !","created_at":null,"updated_at":null}],"4":[{"uid":"4","title":"Bla","message":"Test3!","created_at":null,"updated_at":null}],"success":1}}
But I am still getting the following exception:
Code:
org.json.JSONException: No value for success
The success tag is still being encoded as part of an inner array, not the first array - try this:
PHP:
if (mysql_num_rows($messages) > 0) {
$response["messages"] = array();
while ($row = mysql_fetch_array($messages)) {
$messagesArray= array(
'uid' => $row['id'],
'title' => $row['title'],
'message' => $row['message'],
'created_at' => $row['created_at'],
'updated_at' => $row['updated_at'],
);
array_push($response["messages"], $messagesArray);
}
$response["success"] = 1;
echo json_encode($response);
} else {
$response["success"] = 0;
$response["message"] = "No messages found";
echo json_encode($response);
}
And it's finally working!
Getting the following JSON result:
Code:
{"tag":"message","success":1,"error":0,"messages":[{"uid":"2","title":"","message":"Test1","created_at":null,"updated_at":null},{"uid":"3","title":"","message":"Test2!","created_at":null,"updated_at":null},{"uid":"4","title":"Bla","message":"Test3!","created_at":null,"updated_at":null}]}
And I can successfully loop through my JSON with the following code:
Code:
try {
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
messageItems = json.getJSONArray(MESSAGES);
for (int i = 0; i < messageItems.length(); i++) {
JSONObject obj = messageItems.getJSONObject(i);
String title = obj.getString(TITLE);
String message = obj.getString(MESSAGE);
Log.e("TITLE :", title);
Log.e("MESSAGE :", message);
}
} else {
Log.e("JSON Response", "success == 0");
}
} catch (Exception e) {
e.printStackTrace();
}
Thank you very much! So the problem was that I placed the "success" tag outside my Array?

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected an int

hello i have a problems with app
result
W/System.err﹕ com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected an int but was BOOLEAN at line 1 column 856
code:
private Boolean getCourseInfo() {
CourseSyncTask cs = new CourseSyncTask(mUrl, token, siteInfo.getId());
publishProgress(context.getString(R.string.login_prog_sync_course));
Boolean usrCourseSyncStatus = cs.syncUserCourses();
if (!usrCourseSyncStatus) {
publishProgress(cs.getError());
publishProgress("\n"
+ context.getString(R.string.login_prog_sync_failed));
}
return usrCourseSyncStatus;
}
////////////////////////////////////////////////////////////
public class CourseSyncTask {
String mUrl;
String token;
long siteid;
String error;
/**
*
* @param mUrl
* @param token
* @param siteid
*
*/
public CourseSyncTask(String mUrl, String token, long siteid) {
this.mUrl = mUrl;
this.token = token;
this.siteid = siteid;
}
/**
* Sync all the courses in the current site.
*
* @return syncStatus
*
*/
public Boolean syncAllCourses() {
MoodleRestCourse mrc = new MoodleRestCourse(mUrl, token);
ArrayList<MoodleCourse> mCourses = mrc.getAllCourses();
/** Error checking **/
// Some network or encoding issue.
if (mCourses.size() == 0) {
error = "Network issue!";
return false;
}
// Moodle exception
if (mCourses.size() == 1 && mCourses.get(0).getCourseid() == 0) {
error = "Moodle Exception: User don't have permissions!";
return false;
}
// Add siteid to all courses and update
MoodleCourse course = new MoodleCourse();
List<MoodleCourse> dbCourses;
for (int i = 0; i < mCourses.size(); i++) {
course = mCourses.get(i);
course.setSiteid(siteid);
// Update or save in database
dbCourses = MoodleCourse.find(MoodleCourse.class,
"courseid = ? and siteid = ?", course.getCourseid() + "",
course.getSiteid() + "");
if (dbCourses != null && dbCourses.size() > 0) {
// Set app specific fields explicitly
course.setId(dbCourses.get(0).getId());
course.setIsUserCourse(dbCourses.get(0).getIsUserCourse());
course.setIsFavCourse(dbCourses.get(0).getIsFavCourse());
}
course.save();
}
return true;
}
/**
* Sync all courses of logged in user in the current site.
*
* @return syncStatus
*/
public Boolean syncUserCourses() {
// Get userid
MoodleSiteInfo site = MoodleSiteInfo.findById(MoodleSiteInfo.class,
siteid);
if (site == null)
return false;
int userid = site.getUserid();
MoodleRestCourse mrc = new MoodleRestCourse(mUrl, token);
ArrayList<MoodleCourse> mCourses = mrc.getEnrolledCourses(userid + "");
/** Error checking **/
// Some network or encoding issue.
if (mCourses == null)
return false;
// Some network or encoding issue.
if (mCourses.size() == 0)
return false;
// Moodle exception
if (mCourses.size() == 1 && mCourses.get(0).getCourseid() == 0)
return false;
// Add siteid and isUserCourse to all courses and update
MoodleCourse course = new MoodleCourse();
List<MoodleCourse> dbCourses;
for (int i = 0; i < mCourses.size(); i++) {
course = mCourses.get(i);
course.setSiteid(siteid);
course.setIsUserCourse(true);
// Update or save in database
dbCourses = MoodleCourse.find(MoodleCourse.class,
"courseid = ? and siteid = ?", course.getCourseid() + "",
course.getSiteid() + "");
if (dbCourses.size() > 0) {
// Set app specific fields explicitly
course.setId(dbCourses.get(0).getId());
course.setIsFavCourse(dbCourses.get(0).getIsFavCourse());
}
course.save();
}
return true;
}
/**
* Error message from the last failed sync operation.
*
* @return error
*
*/
public String getError() {
return error;
}
}
////////////////////////////////////////////
public class MoodleRestCourse {
private final String DEBUG_TAG = "MoodleRestCourses";
private String mUrl;
private String token;
public MoodleRestCourse(String mUrl, String token) {
this.mUrl = mUrl;
this.token = token;
}
public ArrayList<MoodleCourse> getAllCourses() {
ArrayList<MoodleCourse> mCourses = new ArrayList<MoodleCourse>();
String format = MoodleRestOption.RESPONSE_FORMAT;
String function = MoodleRestOption.FUNCTION_GET_ALL_COURSES;
try {
// Adding all parameters.
String params = "" + URLEncoder.encode("", "UTF-8");
// Build a REST call url to make a call.
String restUrl = mUrl + "/webservice/rest/server.php" + "?wstoken="
+ token + "&wsfunction=" + function
+ "&moodlewsrestformat=" + format;
// Fetch content now.
MoodleRestCall mrc = new MoodleRestCall();
Reader reader = mrc.fetchContent(restUrl, params);
GsonExclude ex = new GsonExclude();
Gson gson = new GsonBuilder()
.addDeserializationExclusionStrategy(ex)
.addSerializationExclusionStrategy(ex).create();
mCourses = gson.fromJson(reader,
new TypeToken<List<MoodleCourse>>() {
}.getType());
reader.close();
} catch (Exception e) {
Log.d(DEBUG_TAG, "URL encoding failed");
e.printStackTrace();
}
return mCourses;
}
public ArrayList<MoodleCourse> getEnrolledCourses(String userId) {
ArrayList<MoodleCourse> mCourses = new ArrayList<MoodleCourse>();
String format = MoodleRestOption.RESPONSE_FORMAT;
String function = MoodleRestOption.FUNCTION_GET_ENROLLED_COURSES;
try {
// Adding all parameters.
String params = "&" + URLEncoder.encode("userid", "UTF-8") + "="
+ userId;
// Build a REST call url to make a call.
String restUrl = mUrl + "/webservice/rest/server.php" + "?wstoken="
+ token + "&wsfunction=" + function
+ "&moodlewsrestformat=" + format;
// Fetch content now.
MoodleRestCall mrc = new MoodleRestCall();
Reader reader = mrc.fetchContent(restUrl, params);
GsonExclude ex = new GsonExclude();
Gson gson = new GsonBuilder()
.addDeserializationExclusionStrategy(ex)
.addSerializationExclusionStrategy(ex).create();
mCourses = gson.fromJson(reader,
new TypeToken<List<MoodleCourse>>() {
}.getType());
reader.close();
} catch (Exception e) {
Log.d(DEBUG_TAG, "URL encoding failed");
e.printStackTrace();
}
return mCourses;
}
}

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected an int

hello i have a problems with app
result
W/System.err﹕ com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected an int but was BOOLEAN at line 1 column 856
code:
private Boolean getCourseInfo() {
CourseSyncTask cs = new CourseSyncTask(mUrl, token, siteInfo.getId());
publishProgress(context.getString(R.string.login_p rog_sync_course));
Boolean usrCourseSyncStatus = cs.syncUserCourses();
if (!usrCourseSyncStatus) {
publishProgress(cs.getError());
publishProgress("\n"
+ context.getString(R.string.login_prog_sync_failed) );
}
return usrCourseSyncStatus;
}
////////////////////////////////////////////////////////////
public class CourseSyncTask {
String mUrl;
String token;
long siteid;
String error;
/**
*
* @param mUrl
* @param token
* @param siteid
*
*/
public CourseSyncTask(String mUrl, String token, long siteid) {
this.mUrl = mUrl;
this.token = token;
this.siteid = siteid;
}
/**
* Sync all the courses in the current site.
*
* @return syncStatus
*
*/
public Boolean syncAllCourses() {
MoodleRestCourse mrc = new MoodleRestCourse(mUrl, token);
ArrayList<MoodleCourse> mCourses = mrc.getAllCourses();
/** Error checking **/
// Some network or encoding issue.
if (mCourses.size() == 0) {
error = "Network issue!";
return false;
}
// Moodle exception
if (mCourses.size() == 1 && mCourses.get(0).getCourseid() == 0) {
error = "Moodle Exception: User don't have permissions!";
return false;
}
// Add siteid to all courses and update
MoodleCourse course = new MoodleCourse();
List<MoodleCourse> dbCourses;
for (int i = 0; i < mCourses.size(); i++) {
course = mCourses.get(i);
course.setSiteid(siteid);
// Update or save in database
dbCourses = MoodleCourse.find(MoodleCourse.class,
"courseid = ? and siteid = ?", course.getCourseid() + "",
course.getSiteid() + "");
if (dbCourses != null && dbCourses.size() > 0) {
// Set app specific fields explicitly
course.setId(dbCourses.get(0).getId());
course.setIsUserCourse(dbCourses.get(0).getIsUserC ourse());
course.setIsFavCourse(dbCourses.get(0).getIsFavCou rse());
}
course.save();
}
return true;
}
/**
* Sync all courses of logged in user in the current site.
*
* @return syncStatus
*/
public Boolean syncUserCourses() {
// Get userid
MoodleSiteInfo site = MoodleSiteInfo.findById(MoodleSiteInfo.class,
siteid);
if (site == null)
return false;
int userid = site.getUserid();
MoodleRestCourse mrc = new MoodleRestCourse(mUrl, token);
ArrayList<MoodleCourse> mCourses = mrc.getEnrolledCourses(userid + "");
/** Error checking **/
// Some network or encoding issue.
if (mCourses == null)
return false;
// Some network or encoding issue.
if (mCourses.size() == 0)
return false;
// Moodle exception
if (mCourses.size() == 1 && mCourses.get(0).getCourseid() == 0)
return false;
// Add siteid and isUserCourse to all courses and update
MoodleCourse course = new MoodleCourse();
List<MoodleCourse> dbCourses;
for (int i = 0; i < mCourses.size(); i++) {
course = mCourses.get(i);
course.setSiteid(siteid);
course.setIsUserCourse(true);
// Update or save in database
dbCourses = MoodleCourse.find(MoodleCourse.class,
"courseid = ? and siteid = ?", course.getCourseid() + "",
course.getSiteid() + "");
if (dbCourses.size() > 0) {
// Set app specific fields explicitly
course.setId(dbCourses.get(0).getId());
course.setIsFavCourse(dbCourses.get(0).getIsFavCou rse());
}
course.save();
}
return true;
}
/**
* Error message from the last failed sync operation.
*
* @return error
*
*/
public String getError() {
return error;
}
}
////////////////////////////////////////////
public class MoodleRestCourse {
private final String DEBUG_TAG = "MoodleRestCourses";
private String mUrl;
private String token;
public MoodleRestCourse(String mUrl, String token) {
this.mUrl = mUrl;
this.token = token;
}
public ArrayList<MoodleCourse> getAllCourses() {
ArrayList<MoodleCourse> mCourses = new ArrayList<MoodleCourse>();
String format = MoodleRestOption.RESPONSE_FORMAT;
String function = MoodleRestOption.FUNCTION_GET_ALL_COURSES;
try {
// Adding all parameters.
String params = "" + URLEncoder.encode("", "UTF-8");
// Build a REST call url to make a call.
String restUrl = mUrl + "/webservice/rest/server.php" + "?wstoken="
+ token + "&wsfunction=" + function
+ "&moodlewsrestformat=" + format;
// Fetch content now.
MoodleRestCall mrc = new MoodleRestCall();
Reader reader = mrc.fetchContent(restUrl, params);
GsonExclude ex = new GsonExclude();
Gson gson = new GsonBuilder()
.addDeserializationExclusionStrategy(ex)
.addSerializationExclusionStrategy(ex).create();
mCourses = gson.fromJson(reader,
new TypeToken<List<MoodleCourse>>() {
}.getType());
reader.close();
} catch (Exception e) {
Log.d(DEBUG_TAG, "URL encoding failed");
e.printStackTrace();
}
return mCourses;
}
public ArrayList<MoodleCourse> getEnrolledCourses(String userId) {
ArrayList<MoodleCourse> mCourses = new ArrayList<MoodleCourse>();
String format = MoodleRestOption.RESPONSE_FORMAT;
String function = MoodleRestOption.FUNCTION_GET_ENROLLED_COURSES;
try {
// Adding all parameters.
String params = "&" + URLEncoder.encode("userid", "UTF-8") + "="
+ userId;
// Build a REST call url to make a call.
String restUrl = mUrl + "/webservice/rest/server.php" + "?wstoken="
+ token + "&wsfunction=" + function
+ "&moodlewsrestformat=" + format;
// Fetch content now.
MoodleRestCall mrc = new MoodleRestCall();
Reader reader = mrc.fetchContent(restUrl, params);
GsonExclude ex = new GsonExclude();
Gson gson = new GsonBuilder()
.addDeserializationExclusionStrategy(ex)
.addSerializationExclusionStrategy(ex).create();
mCourses = gson.fromJson(reader,
new TypeToken<List<MoodleCourse>>() {
}.getType());
reader.close();
} catch (Exception e) {
Log.d(DEBUG_TAG, "URL encoding failed");
e.printStackTrace();
}
return mCourses;
}
}

Categories

Resources