android Can't catch custom exception thrown by Invoke - android

public class HttpProxy{
public static <T> T getProxy(Class<T> c) {
return (T) Proxy.newProxyInstance(HttpProxy.class.getClassLoader(),
new Class<?>[] { c }, handler);
}
static class HttpInvocationHandler implements InvocationHandler {
#Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object obj = null;
try {
throw new CustomException()
}catch (CustomException e) {
//it work here
throw e;
}
return obj;
}
}
}
call the method:
try{
Res resp = HttpProxy.getProxy(IMODEL.class).login();
if (res != null){
return ok;
}
} catch (CustomException e) {
//after set proguard.config ,its didn't work
Log.e(TAG, Log.getStackTraceString(e));
} catch(Exception e){
//after set proguard.config ,its did here
}
If I set project.properties , I can't catch custom exception.
If I don't not set project.properties it works fine.
like this obfuscation with proguard vs. java.lang.reflect.Proxy

Related

AsyncTask as a separate class

If I have an AsyncTask as a separate class, and I run the AsyncTask from an Activity, will the AsyncTask hold reference to the Activity , just like if it were an inner class of the later?
Or does it solve the issue of memory leak?
Also, will passing the context wrapped up in a WeakReference to the AsyncTask make any change?
you can use like this and get the refrense of activity
public class DeleteUserTask extends AsyncTask<String, String, String> {
private Context context;
private JSONObject Object, Object1;
public static String Success, Exception;
public static boolean isClick;
public DeleteUserTask(Context ctx) {
context = ctx;
}
#Override
protected void onPreExecute() {
OrganizationUser_EditProfileScreen.pb.setVisibility(View.VISIBLE);
}
#Override
protected String doInBackground(String... params) {
try {
ActivityBase.result = null;
Log.e("", "Request-->" + writeJSON().toString());
ActivityBase.PostMethod(context,
WebServiceLinks.UserStatusButtonTask, writeJSON());
Object = new JSONObject(ActivityBase.result);
Object1 = Object
.getJSONObject("OrganizationUserProfileButtonUpdateResult");
Success = Object1.getString("Success");
Exception = Object1.getString("Exception");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
try {
OrganizationUser_EditProfileScreen.pb.setVisibility(View.GONE);
if (ActivityBase.result != null && Success == "true") {
ActivityBase
.GeneralDialog(R.string.account, Exception, context);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public JSONObject writeJSON() {
JSONObject object = new JSONObject();
try {
object.put("OrgID", OrganizationLoginTask.OrgID);
object.put("OrgUserID", Search_Screen.OrgUserID);
object.put("Status", OrganizationUser_EditProfileScreen.Status);
object.put("ModifiedByTypeCode", "2");
object.put("ModifiedSourceCode", "8");
} catch (Exception e) {
e.printStackTrace();
}
return object;
}
}

Thread-safe asynchronous Retrofit request

I'm struggling for few weeks now with this issue. I'm posting geolocation points to a server using Retrofit 2.0. I'm using a IntentService that I call every now and then when I have a new point to post.
For some reason, the server record the same point multiple time creating LOTS of duplicates. It seems that when I call my service and it's already active, it's will query the points and start a new request using some of the same points as was queried by the previous request. I also delete the point only when the request succeed. Is there a way to wait until executing the next batch of points?
How can I wait until all the processed point are sent to the server?
private String postAmazonPoints() throws IOException, JSONException {
ArrayList<EntityPoint> points = new ArrayList<>(GenericDAO.getInstance(EntityPoint.class).queryForAll());
if (points.size() == 0) {
return RESULT_OK;
}
if (connectAmazonApi()) {
int pointSize = points.size();
if(pointSize>5){
for(int i = 0; i<pointSize; i+=5){
int end = i+5;
if( end > pointSize ){
end = pointSize;
}
paginatePostPoint(points.subList(i, end-1));
}
}else{
paginatePostPoint(points.subList(0, pointSize-1));
}
}
return RESULT_OK;
}
private void paginatePostPoint(final List<EntityPoint> points) throws IOException, JSONException {
EntityPoints mPoints = new EntityPoints(points);
Call<ResponseBody> call = amazonServices.postGeopoints(mPoints);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
JSONObject json;
try {
json = (response != null ? new JSONObject(response.body().string()) : null);
Log.e(TAG, json.toString());
if(RESULT_OK.equals(handleJsonRequest(json))){
deleteDatabasePoints(points);
Log.e(TAG, "Point are correctly posted");
}else{
addFirebaseMsg(json.toString());
}
} catch (JSONException e) {
Log.e(TAG, e.getLocalizedMessage());
} catch (IOException e) {
Log.e(TAG, e.getLocalizedMessage());
}
} else {
try {
addFirebaseMsg(response.errorBody().string());
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
addFirebaseMsg(t.getMessage());
}
});
}
private void addFirebaseMsg(String message){
isConnectedToAmz = false;
Bundle params = new Bundle();
params.putString(FirebaseAnalytics.Param.VALUE, message.substring(0, Math.min(message.length(), 30)));
mFirebaseAnalytics.logEvent(Constants.EVENT_TAG_ERROR, params);
Log.d(TAG, message);
}
private boolean connectAmazonApi() {
if (isConnectedToAmz) {
return true;
}
Call<ResponseBody> call = amazonServices.postAuthenticate(settings.getString("token", ""),settings.getString(MyInstanceIDFireService.FIREBASE_TOKEN, ""), settings.getString("id", ""));
String errMsg = "";
try {
ResponseBody response = call.execute().body();
JSONObject json = (response != null ? new JSONObject(response.string()) : null);
if (json != null) {
Log.e(TAG, "Response: " + json.toString());
RetrofitCreator.setAmazonToken(json.getString("token"));
isConnectedToAmz = true;
return true;
}
Log.w(TAG, "Impossible to connect to Amazon API : " + json);
} catch (JSONException e) {
errMsg = e.getMessage();
} catch (IOException e) {
errMsg = e.getMessage();
}
Log.w(TAG, "Impossible to connect to Amazon API");
Bundle params = new Bundle();
params.putLong(FirebaseAnalytics.Param.VALUE, 1);
params.putString(FirebaseAnalytics.Param.VALUE, errMsg.substring(0, Math.min(errMsg.length(), 30)));
mFirebaseAnalytics.logEvent(Constants.EVENT_AMAZON_UNAVAILABLE, params);
return false;
}
You can use .execute instead of .enqueue and request will be synchronous, but in this case you should care about creating another thread for it. Create some service with asynсtask for example with queue.

upgrading retrofit 1 module to retrofit 2

i am rewriting robospice retrofit module with retrofit 2 .
the problem that i have are in 2 methods(saveData , readCacheDataFromFile) :
import com.octo.android.robospice.persistence.exception.CacheCreationException;
import com.octo.android.robospice.persistence.exception.CacheLoadingException;
import com.octo.android.robospice.persistence.exception.CacheSavingException;
import com.octo.android.robospice.persistence.file.InFileObjectPersister;
public class RetrofitObjectPersister<T> extends InFileObjectPersister<T> {
// ============================================================================================
// ATTRIBUTES
// ============================================================================================
private final Converter converter;
// ============================================================================================
// CONSTRUCTOR
// ============================================================================================
public RetrofitObjectPersister(Application application, Converter converter, Class<T> clazz, File cacheFolder) throws CacheCreationException {
super(application, clazz, cacheFolder);
this.converter = converter;
}
public RetrofitObjectPersister(Application application, Converter converter, Class<T> clazz) throws CacheCreationException {
this(application, converter, clazz, null);
}
// ============================================================================================
// METHODS
// ============================================================================================
#Override
public T saveDataToCacheAndReturnData(final T data, final Object cacheKey) throws CacheSavingException {
try {
if (isAsyncSaveEnabled()) {
Thread t = new Thread() {
#Override
public void run() {
try {
saveData(data, cacheKey);
} catch (IOException e) {
Ln.e(e, "An error occured on saving request " + cacheKey + " data asynchronously");
} catch (CacheSavingException e) {
Ln.e(e, "An error occured on saving request " + cacheKey + " data asynchronously");
}
};
};
t.start();
} else {
saveData(data, cacheKey);
}
} catch (CacheSavingException e) {
throw e;
} catch (Exception e) {
throw new CacheSavingException(e);
}
return data;
}
private void saveData(T data, Object cacheKey) throws IOException, CacheSavingException {
// transform the content in json to store it in the cache
TypedOutput typedBytes = converter.toBody(data);
FileOutputStream out = null;
try {
out = new FileOutputStream(getCacheFile(cacheKey));
typedBytes.writeTo(out);
} finally {
if (out != null) {
out.close();
}
}
}
#SuppressWarnings("unchecked")
#Override
protected T readCacheDataFromFile(File file) throws CacheLoadingException {
InputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(file);
final byte[] body = IOUtils.toByteArray(fileInputStream);
TypedInput typedInput = new TypedInput() {
#Override
public String mimeType() {
return "application/json";
}
#Override
public long length() {
return body.length;
}
#Override
public InputStream in() throws IOException {
return new ByteArrayInputStream(body);
}
};
return (T) converter.fromBody(typedInput, getHandledClass());
} catch (FileNotFoundException e) {
// Should not occur (we test before if file exists)
// Do not throw, file is not cached
Ln.w("file " + file.getAbsolutePath() + " does not exists", e);
return null;
} catch (Exception e) {
throw new CacheLoadingException(e);
} finally {
IOUtils.closeQuietly(fileInputStream);
}
}
}
how can i rewrite these methods in retrofit 2 ?
what is the equivalent of TypedOutput and TypedInput interfaces in retrofit 2 ?
i asked Jake Wharton about this , and he replied that The equivalents are :
RequestBody and ResponseBody

Android JSON image download throw MalformedURLException that is already caught

I am downloading images from url's provided by a JSON document. At first my app seems to be working correctly, pulling in and placing images and catching the exceptions when there is no image url in the array element but suddenly it crashes and my error log is showing something to the tune of
Caused by: java.lang.RuntimeException: java.net.MalformedURLException: Protocol not found:
The thing is I have already caught this error as shown below.
If someone could explain to me why this is happening to me and point me in the right direction I will be much obliged.
Image DwnLdr class
public Drawable loadImage (BaseAdapter adapt, ImageView view)
{
this.adapter = adapt;
String url = (String) view.getTag();
if (imageCache.containsKey(url))
{
return imageCache.get(url);
}
else {
new ImageTask().execute(url);
return DEFAULT_ICON;
}
}
private class ImageTask extends AsyncTask<String, Void, Drawable>
{
private String s_url;
#Override
protected Drawable doInBackground(String... params) {
s_url = params[0];
InputStream inStream;
try {
Log.v(debugTag, "Fetching: " + s_url);
URL url = new URL(s_url);
inStream = url.openStream();
} catch (MalformedURLException e) {
Log.v(debugTag, "Malformed: " + e.getMessage());
throw new RuntimeException(e);
} catch (IOException e)
{
Log.d(debugTag, "I/O : " + e.getMessage());
throw new RuntimeException(e);
}
return Drawable.createFromStream(inStream, "src");
}
#Override
protected void onPostExecute(Drawable result) {
super.onPostExecute(result);
synchronized (this) {
imageCache.put(s_url, result);
}
adapter.notifyDataSetChanged();
}
}
View Adapter Class
ListData data = topics.get(position);
try {
long lg = Long.valueOf(data.getPostTime())*1000;
Date date = new Date(lg);
String postTime = new SimpleDateFormat("MM dd, yyyy hh:mma").format(date);
holder.data = data;
holder.listName.setText(data.getTitle());
holder.authorName.setText(data.getAuthor());
holder.postTime.setText(postTime);
holder.redditScore.setText(data.getrScore());
Log.v(DEBUG_TAG, "Cell Created");
}catch (Exception e){
e.printStackTrace();
Log.v(DEBUG_TAG,"Cell Not Created Due to: ",e);
}
if(data.getImageUrl()!=null){
try {
holder.thumbnail.setTag(data.getImageUrl());
Drawable drawable = imgGet.loadImage(this, holder.thumbnail);
if (drawable != null) {
holder.thumbnail.setImageDrawable(drawable);
} else {
holder.thumbnail.setImageResource(R.drawable.filler_icon);
}
}catch (Exception e){
e.printStackTrace();
Log.v(DEBUG_TAG,"no image: ",e);
}
return convertView;
}
Main Class Adapter Set
public static class MyViewHolder {
public TextView listName, authorName, redditScore, postTime;
public Button goButton;
public ImageView thumbnail;
public ListData data;
}
public void setTopics(ArrayList<ListData> data) {
this.data = data;
this.postList.setAdapter(new RedditDataAdapter(this, this.getImg, this.layoutInflater,this.data));
}
Error Log
Caused by: java.lang.RuntimeException: java.net.MalformedURLException: Protocol not found:
at Tasks.RedditIconTask$ImageTask.doInBackground(RedditIconTask.java:60)
at Tasks.RedditIconTask$ImageTask.doInBackground(RedditIconTask.java:46)
at android.os.AsyncTask$2.call(AsyncTask.java:287)
Looks like the image URL is an empty string. Debug your code to learn why is it so. The code you posted doesn't really show where the URL value comes from.
Why you're getting the exception is because you're re-throwing it, wrapped in a RuntimeException:
throw new RuntimeException(e);
I was able to solve my problem by using what laatlto said and changing the code to the following.
protected Drawable doInBackground(String... params) {
s_url = params[0];
InputStream inStream;
Drawable picture=null;
try {
Log.v(debugTag, "Fetching: " + s_url);
URL url = new URL(s_url);
inStream = url.openStream();
picture= Drawable.createFromStream(inStream, "src");
} catch (MalformedURLException e) {
Log.v(debugTag, "Malformed: " + e.getMessage());
} catch (IOException e)
{
Log.d(debugTag, "I/O : " + e.getMessage());
}
return picture;
}

Android: java.lang.VerifyError because of a Generic Class

So I'm developing an Android App and I've had java.lang.VerifyError for the last couple of days. I read in a stackoverflow post that this error was due to a problem in the returns (expected return is not the one it gets).
So I believe this is due to a Generic Class that is casted into a String and I was hoping someone has a solution!
This is the generic Class:
public class ProcessJson {
public enum MessageType{
GetAppName,
GetItemsList
}
public static Object ProcessResult(MessageType messageType, String result) throws MalformedJsonException{
Gson gson = new Gson();
Object returnValue = null;
switch(messageType){
case GetAppName :
returnValue = gson.fromJson(result, String.class);
return returnValue;
case GetItemsList :
returnValue = gson.fromJson(result, Item[].class);
return returnValue;
}
return null;
}
}
Here is where I cast the class:
public void LoginBtn_OnClick(View v){
ItemAdapter adapter = (ItemAdapter)this.itemListView.getAdapter();
//Clearing the ListView
if(adapter != null) {
this.itemListView.setAdapter(null);
}
//Fetch the AplicationName
String username = this.editTextUsername.getText().toString();
String appName = RESTClient.connect("ip/DevTest/WcfApi/Api1.svc/api1/appName", username);
try {
appName = (String)ProcessJson.ProcessResult(MessageType.GetAppName, appName);
appNameTextView.setText("Logged in as: " + appName);
} catch (MalformedJsonException e) {
e.printStackTrace();
appNameTextView.setText("Cannot Login");
}
catch (JsonSyntaxException e){
e.printStackTrace();
appNameTextView.setText("Cannot Login");
}
//Fetch the itemList
String itemList = RESTClient.connect("ip/DevTest/WcfApi/Api1.svc/api1/items", username);
try{
Item[] items = (Item[])ProcessJson.ProcessResult(MessageType.GetItemsList, itemList);
//Binding itemList to UI
//ItemAdapter itemAdapter = new ItemAdapter(this, R.layout.item_row, items);
//this.itemListView.setAdapter(itemAdapter);
} catch (MalformedJsonException e) {
e.printStackTrace();
appNameTextView.setText("Cannot Login");
}
catch (JsonSyntaxException e){
e.printStackTrace();
appNameTextView.setText("Cannot Login");
}
}
I manage to avoid the crash when I put the two try/catch blocks as a comment. This is what lead me to believe the problem is due to the ProcessJson class.
Thanks in advance.
Try this workaround, it might solve your problem.

Categories

Resources