Instantiation Exception - android

Instantiation Exception in this code:
public static ObjType DeepCloneObject(ObjType Object) throws IllegalAccessException, InstantiationException {
Object Clone = Object.getClass().newInstance();
for (Field field : Object.getClass().getDeclaredFields()) {
field.setAccessible(true);
// Skip if filed is null or final
if(field.get(Object) == null || Modifier.isFinal(field.getModifiers())){
continue;
}
if(field.getType().isPrimitive() || field.getType().equals(String.class)
|| Objects.equals(field.getType().getSuperclass(), Number.class)
|| field.getType().equals(Boolean.class)){
field.set(Clone, field.get(Object));
}else{
Object childObj = field.get(Object);
if(childObj == Object){ // Self-reference check
field.set(Clone, Clone);
}else{
field.set(Clone, DeepCloneObject(field.get(Object)));
}
}
}
return (ObjType)Clone;
}
Usage:
public static DownloadTask CreateTaskFromFiles(ArrayList Indexes, DownloadTask OriginalTask) throws IllegalAccessException, InstantiationException {
// Warning: Slow algorithm
DownloadTask NewTask = Utils.DeepCloneObject(OriginalTask);
if (NewTask != null) {
NewTask.Files = new ArrayList<DownloadTaskFile>();
for (int i = 0; i < OriginalTask.Files.size(); ++i) {
if (!Indexes.contains(i)) {
NewTask.Files.remove(i);
}
}
}
return NewTask;
}
==============================================================
LogCat:
Failed to clone object - com.gamedevers.blackazerbaijan_sa_mp.core.SAMP.Components.DownloadSystem.DownloadTask

Related

Is there any way to run WorkManager's requests non-persistently?

I've switched to WorkManager and use it in almost all cases. Methods, that return LiveData by request ID, are very convenient for UI-binding.
I have a task to log in to a remote server. So, I would like to keep on using WorkManagers API for this task but do not need total DB-level persistence. I need keeping track of my task only in app lifecycle (e.x. during orientation changes) and, of cause, no posting my credentials to service DB.
Is there any way to enqueue and keep track if my background tasks in WorkManager manner but with no persistence, just for running process?
OK, I implemented my own small WorkManager based on WorkManager's classes but it's quite hard to support.
static class ThreadWorkManager extends TinyWorkManager {
static final String TAG = ThreadWorkManager.class.getSimpleName();
final ExecutorService executor = Executors.newFixedThreadPool(10);
final Executor uiExecutor = Utils::uiPost;
final HashMap<UUID, WorkData> workDatum = new HashMap<>();
final WeakHashMap<MutableLiveData<WorkInfo>, UUID> liveIdDatum = new WeakHashMap<>();
final WeakHashMap<MutableLiveData<WorkInfo>, String> liveTagDatum = new WeakHashMap<>();
static WorkInfo fromWorkData(UUID id, WorkData workData) {
return workData != null ? new WorkInfo(id, workData.spec.state, workData.spec.output, workData.tagList) : null;
}
static class WorkData {
final ListenableWorker worker;
final WorkSpec spec;
final Set<String> tags;
final List<String> tagList;
long time = System.currentTimeMillis();
Runnable startLater;
WorkData(ListenableWorker worker, WorkSpec spec) {
this.worker = worker;
this.spec = spec;
this.tags = worker.getTags();
this.tagList = new ArrayList<>(tags);
}
}
void onWorkChanged(UUID id) {
//if (BuildConfig.DEBUG && Thread.currentThread() != ui.getLooper().getThread())
// throw new AssertionError();
WorkData workData = workDatum.get(id);
if (workData == null) return;
workData.time = System.currentTimeMillis();
WorkInfo workInfo = fromWorkData(id, workData);
//TODO remove finished workdata and id livedata
while (true) {
try {
for (Map.Entry<MutableLiveData<WorkInfo>, UUID> entry : liveIdDatum.entrySet())
if (entry.getValue().equals(id))
entry.getKey().setValue(workInfo);
break;
} catch (ConcurrentModificationException e) {
Log.w(TAG, "concurrent 1");
}
}
while (true) {
try {
for (Map.Entry<MutableLiveData<WorkInfo>, String> entry : liveTagDatum.entrySet())
if (workData.tags.contains(entry.getValue()))
entry.getKey().setValue(workInfo);
break;
} catch (ConcurrentModificationException e) {
Log.w(TAG, "concurrent 2");
}
}
}
void scheduleWork(UUID id, WorkData workData, long delay) {
workData.spec.state = WorkInfo.State.ENQUEUED;
onWorkChanged(id);
uiPost(workData.startLater = () -> {
workData.startLater = null;
workData.spec.state = WorkInfo.State.RUNNING;
onWorkChanged(id);
ListenableFuture<ListenableWorker.Result> future = workData.worker.startWork();
future.addListener(new WorkerListener(id, future), uiExecutor);
}, delay);
}
#Override
public void enqueue(WorkRequest workRequest) {
//executor.submit(new WorkUnit(workRequest));
try {
Class<? extends ListenableWorker> workerClass = (Class<? extends ListenableWorker>) Class.forName(workRequest.getWorkSpec().workerClassName);
Class[] types = {Context.class, WorkerParameters.class};
Constructor constructor = workerClass.getConstructor(types);
UUID id = workRequest.getId();
WorkSpec workSpec = workRequest.getWorkSpec();
ListenableWorker worker = (ListenableWorker) constructor.newInstance(appContext, new WorkerParameters(
id,
workSpec.input,
workRequest.getTags(),
null,
workSpec.runAttemptCount,
executor,
null,
null));
WorkData workData = new WorkData(worker, workRequest.getWorkSpec());
workDatum.put(worker.getId(), workData);
if (workSpec.initialDelay > 0) {
scheduleWork(id, workData, workSpec.initialDelay);
} else {
workSpec.state = WorkInfo.State.RUNNING;
onWorkChanged(id);
ListenableFuture<ListenableWorker.Result> future = worker.startWork();
future.addListener(new WorkerListener(worker.getId(), future), uiExecutor);
}
} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | InvocationTargetException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
class WorkerListener implements Runnable {
private final UUID id;
private final ListenableFuture<ListenableWorker.Result> future;
WorkerListener(UUID id, ListenableFuture<ListenableWorker.Result> future) {
this.id = id;
this.future = future;
}
#Override
public void run() {
WorkData workData = workDatum.get(id);
if (workData == null) return;
try {
ListenableWorker.Result r = future.get();
if (r == null || r instanceof ListenableWorker.Result.Failure) {
workData.spec.state = WorkInfo.State.FAILED;
if (r != null)
workData.spec.output = ((ListenableWorker.Result.Failure) r).getOutputData();
onWorkChanged(workData.worker.getId());
} else if (r instanceof ListenableWorker.Result.Success) {
workData.spec.state = WorkInfo.State.SUCCEEDED;
workData.spec.output = ((ListenableWorker.Result.Success) r).getOutputData();
onWorkChanged(id);
if(workData.spec.isPeriodic())
scheduleWork(id, workData, workData.spec.intervalDuration);
} else if (r instanceof ListenableWorker.Result.Retry) {
workData.spec.state = WorkInfo.State.ENQUEUED;
onWorkChanged(id);
//TODO spec.backoffPolicy
scheduleWork(id, workData, workData.spec.backoffDelayDuration);
}
Log.d(TAG, workData.worker.getClass().getSimpleName() + " " + id + " " + workData.spec.state);
} catch (ExecutionException | InterruptedException e) {
Log.e(TAG, workData.worker.getClass().getSimpleName() + " " + id + " no future");
}
}
}
#Override
public WorkInfo getWorkInfo(String tag) {
WorkData tagWorkData = null;
for (WorkData workData : workDatum.values())
if (workData.tags.contains(tag) && (tagWorkData == null || tagWorkData.time < workData.time))
tagWorkData = workData;
return tagWorkData != null ? fromWorkData(UUID.fromString(tagWorkData.spec.id), tagWorkData) : null;
}
#Override
public LiveData<WorkInfo> getWorkInfoLiveData(UUID id) {
if (BuildConfig.DEBUG && Thread.currentThread() != ui.getLooper().getThread())
throw new AssertionError();
MutableLiveData<WorkInfo> liveData = null;
while (true) {
try {
for (Map.Entry<MutableLiveData<WorkInfo>, UUID> entry : liveIdDatum.entrySet())
if (entry.getValue().equals(id)) {
liveData = entry.getKey();
break;
}
break;
} catch (ConcurrentModificationException e) {
Log.w(TAG, "concurrent 3");
}
}
if (liveData == null) {
liveIdDatum.put(liveData = new MutableLiveData<>(), id);
WorkInfo workInfo = fromWorkData(id, workDatum.get(id));
if (workInfo != null)
liveData.setValue(workInfo);
}
return liveData;
}
#Override
public LiveData<WorkInfo> getWorkInfoLiveData(String tag) {
if (BuildConfig.DEBUG && Thread.currentThread() != ui.getLooper().getThread())
throw new AssertionError();
MutableLiveData<WorkInfo> liveData = null;
while (true) {
try {
for (Map.Entry<MutableLiveData<WorkInfo>, String> entry : liveTagDatum.entrySet())
if (entry.getValue().equals(tag)) {
liveData = entry.getKey();
break;
}
break;
} catch (ConcurrentModificationException e) {
Log.w(TAG, "concurrent 4");
}
}
if (liveData == null) {
liveTagDatum.put(liveData = new MutableLiveData<>(), tag);
WorkInfo workInfo = getWorkInfo(tag);
if (workInfo != null)
liveData.setValue(workInfo);
}
return liveData;
}
#Override
public void cancelWork(UUID id) {
WorkData workData = workDatum.get(id);
if (workData != null && !workData.spec.state.isFinished()) {
if (workData.startLater != null) {
uiRemove(workData.startLater);
workData.startLater = null;
}
workData.worker.stop();
workData.spec.state = WorkInfo.State.CANCELLED;
onWorkChanged(id);
}
}
#Override
public void cancelWork(String tag) {
for (WorkData workData : workDatum.values())
if (workData.tags.contains(tag))
cancelWork(UUID.fromString(workData.spec.id));
}
}
You shouldn't be using WorkManager if you don't need the tasks to persist. You should, instead, find a different solution as per the Background Processing Guide: https://developer.android.com/guide/background/

finding in an array if specific fileds exists or not

This is my api
{}JSON
[]products
{}0
product-name : "Fiting"
product-id : "1"
product-description : "Door"
product-image : "https://image/logo.jpg"
product-categoryid : "2"
category-name : "Furniture"
{}1
product-name : "Bathroom"
product-id : "2"
product-description : "Services"
product-image : "https://image/logo.jpg"
product-categoryid : "1"
category-name : "Plumber"
subcategory-id : "1"
subcategory-name : "Bathroom"
subCategoryDetailModelClass.setSubCategoryId(productObject.getInt("subcategory-id"));
subCategoryDetailModelClass.setSubCategoryName(productObject.getString("subcategory-name"));
i cannot add subcategory-id,subcategory-name in my arraylist since it is not available at 0th position.....so how to check condition that if in api subcategory-id,subcategory-name is not available add other items in the list
StringRequest stringRequest = new StringRequest(Request.Method.GET,URLs.productURL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d("zsded", response.toString());
try {
JSONObject obj = new JSONObject(response);
JSONArray productArray = obj.getJSONArray("products");
//now looping through all the elements of the json array
for (int i = 0; i < productArray.length(); i++) {
JSONObject productObject = productArray.getJSONObject(i);
SubCategoryDetailModelClass subCategoryDetailModelClass = new SubCategoryDetailModelClass();
// if(productObject.getInt("subcategory-id"))
subCategoryDetailModelClass.setProduct_name(productObject.getString("product-name"));
subCategoryDetailModelClass.setProduct_id(productObject.getInt("product-id"));
subCategoryDetailModelClass.setProduct_desc(productObject.getString("product-description"));
subCategoryDetailModelClass.setProduct_imgURL(productObject.getString("product-image"));
subCategoryDetailModelClass.setProduct_CategoryId(productObject.getInt("product-categoryid"));
subCategoryDetailModelClass.setProduct_Category_Name(productObject.getString("category-name"));
subCategoryDetailModelClass.setSubCategoryId(productObject.getInt("subcategory-id"));
subCategoryDetailModelClass.setSubCategoryName(productObject.getString("subcategory-name"));
subCategoryListDetailModelClassArray.add(subCategoryDetailModelClass);
Log.d("subcatdetail", String.valueOf(subCategoryDetailModelClass));
}
Use this class
public class JSONHelper {
public static String getString(JSONObject json, String tag) throws JSONException {
if(mJSONValueAvailable(json, tag)) {
return json.getString(tag);
}
return "";
}
public static int getInt(JSONObject json, String tag) throws JSONException {
if(mJSONValueAvailable(json, tag)) {
if(json.get(tag) instanceof String) {
if(json.getString(tag).equalsIgnoreCase("None")) {
return -1;
}
if(!json.getString(tag).equals("")) {
return Integer.parseInt(json.getString(tag));
} else {
return -1;
}
}
return json.getInt(tag);
}
return -1;
}
public static boolean getBoolean(JSONObject json, String tag) throws JSONException {
if(mJSONValueAvailable(json, tag)) {
Object value = json.get(tag);
if(value instanceof String) {
return PrimitiveHelper.StringToBoolean((String) value);
} else if (value instanceof Integer) {
return PrimitiveHelper.IntegerToBoolean((int)value);
}
return json.getBoolean(tag);
}
return false;
}
public static Boolean getBooleanBoxed(JSONObject json, String tag) throws JSONException {
if(mJSONValueAvailable(json, tag)) {
Object value = json.get(tag);
if(value instanceof String) {
return PrimitiveHelper.StringToBooleanBoxed((String) value);
} else if (value instanceof Integer) {
return PrimitiveHelper.IntegerToBooleanBoxed((int) value);
}
return json.getBoolean(tag);
}
return null;//false;
}
private static boolean mJSONValueAvailable(JSONObject json, String tag) {
return json.has(tag) && !json.isNull(tag);
}
// private static Boolean mJSONValueAvailableBoxed(JSONObject json, String tag) {
// return json.has(tag) && !json.isNull(tag);//
// }
public static JSONArray sortJsonArray(JSONArray array, String sort) {
final String sortKey = sort;
//Logger.d("sortJSONArray by::: " + sortKey);
List<JSONObject> jsons = new ArrayList<JSONObject>();
try {
for (int i = 0; i < array.length(); i++) {
jsons.add(array.getJSONObject(i));
}
Collections.sort(jsons, new Comparator<JSONObject>() {
#Override
public int compare(JSONObject lhs, JSONObject rhs) {
try {
String lid = lhs.getString(sortKey);
String rid = rhs.getString(sortKey);
// Here you could parse string id to integer and then compare.
return lid.compareTo(rid);
} catch (JSONException e) {
e.printStackTrace();
}
return 0;
}
});
} catch (JSONException e) {
e.printStackTrace();
}
return new JSONArray(jsons);
}
}
Call this as follows
subCategoryDetailModelClass.setProduct_name(JSONHelper.getString(productObject, "product-name"));
subCategoryDetailModelClass.setProduct_id(JSONHelper.getInt(productObject,"product-id"));
subCategoryDetailModelClass.setProduct_desc(JSONHelper.getString(productObject, "product-description"));
subCategoryDetailModelClass.setProduct_imgURL(JSONHelper.getString(productObject, "product-image"));
subCategoryDetailModelClass.setProduct_CategoryId(JSONHelper.getInt(productObject,"product-categoryid"));
subCategoryDetailModelClass.setProduct_Category_Name(JSONHelper.getString(productObject, "category-name"));
subCategoryDetailModelClass.setSubCategoryId(JSONHelper.getInt(productObject, "subcategory-id"));
subCategoryDetailModelClass.setSubCategoryName(JSONHelper.getString(productObject,"subcategory-name"));
subCategoryListDetailModelClassArray.add(subCategoryDetailModelClass);
Use Opt methods, For e.g.
optInt(String name, int fallback)
Returns the value mapped by name if it exists and is an int or can be
coerced to an int, or fallback otherwise.
There are optMethods for mostly primitive datatypes, check here

switching between open applications android through adb

I writed a robotium test that runs a test on a apk file. The test runs on a apk file in a debug mode. the test clicks and inserts data in the app.
The problem is, that sometimes a user hit on a link in a app, and opend a new app/website on the device, and now the root app is not visible.
there is a way to make it visible through the adb?
this is the main class of the test:
package genericTest.test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import android.annotation.SuppressLint;
import android.app.KeyguardManager;
import android.content.Context;
import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
import android.view.View;
import com.robotium.solo.Solo;
#SuppressWarnings("rawtypes")
public class Main extends ActivityInstrumentationTestCase2 {
private FunctonsForViews mFunctonsForViews;
private Random mRand;
private Solo mSolo;
private static final String LAUNCHER_ACTIVITY_FULL_CLASSNAME = "com.hobbyistsoftware.android.vlcremote_us.main";
private final int DELAY = 50;
private final int SCREEN_SIZE = 1280;
private final int ERROR_COUNT_LIMIT = 10;
private final int CLICK_ON_LOOP_LIMIT = 8;
private final int WHAITING_FOR_VIEWS_LIMIT = 10;
private final int LOOP_LIMIT = 10000;
private static Class launcherActivityClass;
private static int error_count = 0;
static {
try {
launcherActivityClass = Class
.forName(LAUNCHER_ACTIVITY_FULL_CLASSNAME);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
#SuppressLint("NewApi")
#SuppressWarnings("unchecked")
public Main() throws ClassNotFoundException {
super(null, launcherActivityClass);
}
protected void setUp() throws Exception {
setActivityInitialTouchMode(true);
mSolo = new Solo(getInstrumentation(), getActivity());
Context context = getActivity();
KeyguardManager km =
(KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
if (km.inKeyguardRestrictedInputMode())
{
KeyguardManager.KeyguardLock lock = km.newKeyguardLock("some_tag");
lock.disableKeyguard();
SystemClock.sleep(2000);
}
setActivityInitialTouchMode(true);
}
/*
* runs the test for the app.
*/
public void testMethod()
{
mFunctonsForViews = new FunctonsForViews(mSolo);
mSolo.sleep(DELAY * DELAY);
mRand = new Random();
/*
* the test will take place in the loop, and will be limit in time.
* in every iteration it will get the vies in activity's, and run a test on a random view.
*/
//for(int i=0 ; i<LOOP_LIMIT ; i++)
while(true)
{
mSolo.unlockScreen();
ArrayList Views = mSolo.getViews();
int arraySize = Views.size();
if (arraySize == 0)// now View in activity.
{
whenNoViewsInScreen(Views, arraySize);
}
if (arraySize != 0)
{
int ViewIndexInArray = mRand.nextInt(arraySize + 2);
if (ViewIndexInArray == arraySize)
{
mSolo.scrollDown();
}
else if (ViewIndexInArray == arraySize + 1)
{
if (!mSolo.getCurrentActivity().getClass().toString().split(" ")[1].equals
(LAUNCHER_ACTIVITY_FULL_CLASSNAME))
{
goingBack();
}
}
else
{
View randomView = (View)(Views.get(ViewIndexInArray));
runTestOnOneView(randomView);
}
}
}
}
/*
* performing clicks onScreen()
*/
public void myClickOnScreen()
{
try {
mSolo.unlockScreen();
mSolo.clickOnScreen(mRand.nextInt(SCREEN_SIZE), mRand.nextInt(SCREEN_SIZE));
} catch (Exception e) {
e.printStackTrace();
error_count++;
} catch (Error e2) {
error_count++;
e2.printStackTrace();
}
}
/*
* there is no Views available.
* we will try pressing on screen or the goBack function.
*/
public void whenNoViewsInScreen(ArrayList Views, int arraySize)
{
for (int j = 0; j < WHAITING_FOR_VIEWS_LIMIT; j++)
{
for (int k= 0; k < CLICK_ON_LOOP_LIMIT; k++)
{
myClickOnScreen();
}
Views = mSolo.getViews();
arraySize = Views.size();
if (arraySize != 0)
{
return;
}
mSolo.sleep(DELAY);
Views = mSolo.getViews();
arraySize = Views.size();
if (arraySize != 0)
{
return;
}
}
if (!mSolo.getCurrentActivity().getClass().toString().split(" ")[1].equals
(LAUNCHER_ACTIVITY_FULL_CLASSNAME))
{
goingBack();
}
mSolo.sleep(DELAY);
return;
}
public void runTestOnOneView(View randomView)
{
String rawViewName = randomView.getClass().getName();
String viewName = parseRawViewName(rawViewName);
if (viewName.contains("ActionBarContainer"))
{
return;
}
MyRunnable myRunnable = mFunctonsForViews.getMethodMap().get(viewName);
try{
if (myRunnable != null)
{
myRunnable.run((View)randomView);
}
else // view not in map.
{
boolean inMap = false;
Iterator it = mFunctonsForViews.getMethodMap().entrySet().iterator();
/*
* iterating in case the View is a version of one of View in map
* example:
* View is "CustomEditText", and map contains o view "EditText".
*/
while (it.hasNext())
{
Map.Entry pairs = (Map.Entry)it.next();
if ( viewName.contains((String)pairs.getKey()) )
{
inMap = true;
// next two lines changed
myRunnable = (MyRunnable)(pairs.getValue());
myRunnable.run((View)randomView);
break;
}
}
if (inMap == false)
{
if (viewName.contains("Layout"))
{
return;
}
mSolo.clickOnView((View)randomView);
}
error_count = 0;
}
}catch(Exception exception)
{
exception.printStackTrace();
if(error_count > ERROR_COUNT_LIMIT &&
!(mSolo.getCurrentActivity().getClass().toString().split(" ")[1].equals(LAUNCHER_ACTIVITY_FULL_CLASSNAME)))
{
goingBack();
error_count = 0;
}
return;
}catch(Error error)
{
error.printStackTrace();
error_count ++;
if(error_count > ERROR_COUNT_LIMIT &&
!(mSolo.getCurrentActivity().getClass().toString().split(" ")[1].equals(LAUNCHER_ACTIVITY_FULL_CLASSNAME)))
{
goingBack();
error_count = 0;
}
return;
}
mSolo.sleep(DELAY);
}
/*
* performs a goBack command surrounded with catch/try
*/
public void goingBack()
{
try {
String currentActivity = mSolo.getCurrentActivity().getClass().toString();
mSolo.goBack();
if (mSolo.getCurrentActivity().getClass().toString().equals(currentActivity))
{
for (int i = 0; i< 20; i++)
{
myClickOnScreen();
}
}
} catch (Exception e) {
e.printStackTrace();
} catch (Error e) {
e.printStackTrace();
}
}
/*
* extract the name of View from raw View name.
* example:
* raw View name: android.widget.TextView
* raw View name:TextView
*/
public String parseRawViewName(String rawViewName)
{
if (rawViewName.contains(" "))
{
String [] array = rawViewName.split(" ");
rawViewName = array [0];
}
if (rawViewName.contains(".") || rawViewName.contains("$"))
{
String [] array = rawViewName.split("\\.|$");
rawViewName = array [array.length-1];
}
return rawViewName;
}
public void tearDown() throws Exception {
mSolo.finishOpenedActivities();
}
}

asmak packet listener and custom IQProvider not triggering / called

I'm using asmack the latest version (asmack-android-8-source-0.8.3) in a android project and I'm trying to communicate with the server by sending multiple IQs and receiving responses.
I receive the response and it's parsed correctly but the package listener it's not triggering.
I have the following code:
vCard_IQProvider.java
public class vCard_IQProvider implements IQProvider
{
public static final String NAMESPACE = "vcard-temp";
public static final String ELEMENT_NAME = "vCard";
public static final String LAST_STATUS = "LAST_STATUS";
public static final String LAST_STATUS_DESCRIPTION = "LAST_STATUS_DESCRIPTION";
public static final String WORK_TIME_RANGE = "WORK_TIME_RANGE";
public static final String SOUND_SETTINGS = "SOUND_SETTINGS";
public static final String AUTO_LOCATION_MACHINE_DATA = "AUTO_LOCATION_MACHINE_DATA";
public static final String AUTO_LOCATION = "AUTO_LOCATION";
public static final String AUTO_LOCATION_ENABLED = "AUTO_LOCATION_ENABLED";
public static final String AUTO_ONLINE = "AUTO_ONLINE";
public static final String HIDEACTIONNOTIFICATIONS = "HideActionNotifications";
public static final String AUTO_CONNECT = "AUTO_CONNECT";
public static final String AUTO_OFFLINE_WORK_TIME = "AUTO_OFFLINE_WORK_TIME";
public static final String AUTO_RELOGIN = "AUTO_RELOGIN";
public static final String CONNECTED_VIA_INTERNET = "CONNECTED_VIA_INTERNET";
public static final String MINIMIZE_CHAT = "MINIMIZE_CHAT";
public static final String PROMPT_PROJECT_SWITCH = "PROMPT_PROJECT_SWITCH";
public static final String MACHINE_NAME = "MACHINE_NAME";
public static final String MROFFICE_VER = "MROFFICE_VER";
public static final String WORK = "WORK";
public static final String LOCALITY = "LOCALITY";
public static final String TIMESTAMP = "timestamp";
public static final String REGION = "REGION";
public static final String EXT = "EXT";
public static final String LAST_ACTIVITY_TS = "LAST_ACTIVITY_TS";
public static final String FUTURE_STATUS = "FUTURE_STATUS";
public static final String FUTURE_STATUS_DESCRIPTION = "FUTURE_STATUS_DESCRIPTION";
public static final String FUTURE_STATUS_TS = "FUTURE_STATUS_TS";
public static final String CUSTOM = "CUSTOM";
public static final String PREF = "PREF";
private Map<String, String> list = new HashMap<String, String>();
#Override
public IQ parseIQ(XmlPullParser parser) throws Exception
{
String name;
boolean isEmpty;
boolean done = false;
while(parser.next() != XmlPullParser.END_DOCUMENT && false == done)
{
name = parser.getName();
switch (parser.getEventType())
{
case XmlPullParser.START_TAG:
{
isEmpty = parser.isEmptyElementTag();
if(name.equalsIgnoreCase(LAST_STATUS) && false == isEmpty)
{
list.put(LAST_STATUS, parser.nextText());
}
else if(name.equalsIgnoreCase(LAST_STATUS_DESCRIPTION) && false == isEmpty)
{
list.put(LAST_STATUS_DESCRIPTION , parser.nextText());
}
else if(name.equalsIgnoreCase(WORK_TIME_RANGE) && false == isEmpty)
{
list.put(WORK_TIME_RANGE, parser.nextText());
}
else if(name.equalsIgnoreCase(SOUND_SETTINGS) && false == isEmpty)
{
list.put(SOUND_SETTINGS, parser.nextText());
}
else if(name.equalsIgnoreCase(AUTO_LOCATION_MACHINE_DATA) && false == isEmpty)
{
list.put(AUTO_LOCATION_MACHINE_DATA, parser.nextText());
}
else if(name.equalsIgnoreCase(AUTO_LOCATION) && false == isEmpty)
{
list.put(AUTO_LOCATION, parser.nextText());
}
else if(name.equalsIgnoreCase(AUTO_LOCATION_ENABLED) && false == isEmpty)
{
list.put(AUTO_LOCATION_ENABLED, parser.nextText());
}
else if(name.equalsIgnoreCase(AUTO_ONLINE) && false == isEmpty)
{
list.put(AUTO_ONLINE, parser.nextText());
}
else if(name.equalsIgnoreCase(HIDEACTIONNOTIFICATIONS) && false == isEmpty)
{
list.put(HIDEACTIONNOTIFICATIONS, parser.nextText());
}
else if(name.equalsIgnoreCase(AUTO_CONNECT) && false == isEmpty)
{
list.put(AUTO_CONNECT, parser.nextText());
}
else if(name.equalsIgnoreCase(AUTO_OFFLINE_WORK_TIME) && false == isEmpty)
{
list.put(AUTO_OFFLINE_WORK_TIME, parser.nextText());
}
else if(name.equalsIgnoreCase(AUTO_RELOGIN) && false == isEmpty)
{
list.put(AUTO_RELOGIN, parser.nextText());
}
else if(name.equalsIgnoreCase(CONNECTED_VIA_INTERNET) && false == isEmpty)
{
list.put(CONNECTED_VIA_INTERNET, parser.nextText());
}
else if(name.equalsIgnoreCase(MINIMIZE_CHAT) && false == isEmpty)
{
list.put(MINIMIZE_CHAT, parser.nextText());
}
else if(name.equalsIgnoreCase(PROMPT_PROJECT_SWITCH) && false == isEmpty)
{
list.put(PROMPT_PROJECT_SWITCH, parser.nextText());
}
else if(name.equalsIgnoreCase(MACHINE_NAME) && false == isEmpty)
{
list.put(MACHINE_NAME, parser.nextText());
}
else if(name.equalsIgnoreCase(MROFFICE_VER) && false == isEmpty)
{
list.put(MROFFICE_VER, parser.nextText());
}
else if(name.equalsIgnoreCase(WORK) && false == isEmpty)
{
list.put(WORK, parser.nextText());
}
else if(name.equalsIgnoreCase(LOCALITY) && false == isEmpty)
{
list.put(LOCALITY, parser.nextText());
}
else if(name.equalsIgnoreCase(TIMESTAMP) && false == isEmpty)
{
list.put(TIMESTAMP, parser.nextText());
}
else if(name.equalsIgnoreCase(REGION) && false == isEmpty)
{
list.put(REGION, parser.nextText());
}
else if(name.equalsIgnoreCase(EXT) && false == isEmpty)
{
list.put(EXT, parser.nextText());
}
else if(name.equalsIgnoreCase(LAST_ACTIVITY_TS) && false == isEmpty)
{
list.put(LAST_ACTIVITY_TS, parser.nextText());
}
else if(name.equalsIgnoreCase(FUTURE_STATUS) && false == isEmpty)
{
list.put(FUTURE_STATUS, parser.nextText());
}
else if(name.equalsIgnoreCase(FUTURE_STATUS_DESCRIPTION) && false == isEmpty)
{
list.put(FUTURE_STATUS_DESCRIPTION, parser.nextText());
}
else if(name.equalsIgnoreCase(FUTURE_STATUS_TS) && false == isEmpty)
{
list.put(FUTURE_STATUS_TS, parser.nextText());
}
else if(name.equalsIgnoreCase(CUSTOM) && false == isEmpty)
{
list.put(CUSTOM, parser.nextText());
}
else if(name.equalsIgnoreCase(PREF) && false == isEmpty)
{
list.put(PREF, parser.nextText());
}
break;
}
case XmlPullParser.END_TAG:
{
done = ELEMENT_NAME.equalsIgnoreCase(name);
break;
}
}
}
name = null;
return new vCard_IQ(list);
}
}
vCard_IQ.java
public class vCard_IQ extends IQ
{
public static final String ID = "vcard";
private static Map<String, String> list;
private static boolean finishedParsing = false;
public vCard_IQ(Map<String, String> l)
{
if(null == list)
{
list = new HashMap<String, String>();
}
list.clear();
list.putAll(l);
finishedParsing = true;
}
#Override
public String getChildElementXML()
{
return null;
}
public static final Map<String, String> getData()
{
return list;
}
public static void setFinishedParsingToFalse()
{
finishedParsing = false;
}
public static final boolean finishedParsing()
{
return finishedParsing;
}
}
I add the provider:
ProviderManager.getInstance().addIQProvider(vCard_IQProvider.ELEMENT_NAME, vCard_IQProvider.NAMESPACE, new vCard_IQProvider());
and the package listener:
connection.addPacketListener(new PacketListener()
{
#Override
public void processPacket(Packet p)
{
if(p.getPacketID().equals(vCard_IQ.ID))
{
vCard_IQ pp = (vCard_IQ)p;
//access the parsed data
//vCard_IQ.getData().get.......
pp = null;
}
}
},
new PacketFilter()
{
#Override
public boolean accept(Packet arg0)
{
return true;
}
});
The packet filter is set to accept all packets, the listner is not triggering for some reason. I can see in the debugger that the server is sending the responses.
I even tried to bypass the listener by creating an asynk task an waiting in the background thread until the response is parsed and than I access it. Now it works only for the first iq sent - I receive a response and it's parsed correctly, but for the rest I can see in the debugger that the server it's sending responses but it never reaches the parser. The parser it's never called.
Asynk<Void, Void, Void> asynk = new Asynk<Void, Void, Void>()
{
Packet iq_vcard;
#Override
protected Void doInBackground(Void... params)
{
for(String s : names_list)
{
final String name = s;
iq_vcard = new Packet()
{
#Override
public String toXML()
{
String str = String.format("<iq from='%s' to='%s' type='get' id='" + vCard_IQ.ID + "'><vCard xmlns='vcard-temp'/></iq>",
sharedPrefs.getString(LogIn.USERNAME, "") + "#" + sharedPrefs.getString(Settings_LogIn.DOMAIN, Settings_LogIn.ERROR) + "/iOffice",
name + "#" + sharedPrefs.getString(Settings_LogIn.DOMAIN, Settings_LogIn.ERROR));
Log.e("iq_vcard", str);
return str;
}
};
connection().sendPacket(iq_vcard);
iq_vcard = null;
while(false == vCard_IQ.finishedParsing())
{
try
{
Thread.sleep(1000);
Log.e("TAG", "waiting to finish parsing...");
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
//access the parsed data
//vCard_IQ.getData().get.......
vCard_IQ.setFinishedParsingToFalse();
}
return null;
}
#Override
protected void onPostExecute(Void result)
{
}
};
asynk.execute();
Any suggestions on what's wrong?
This is a bug in aSmack and after numerous attempts at fixing this issue, failed attempts of compiling aSmack myself following this tutorial and trying anything that I could think of, I did the following: I created a new package in my android project and dumped all of the aSmack's java classes there. This way I let eclipse compile aSmack and I got a better control over it's code.
The problem was that every time I would receive an custom iq response from server, in PacketParserUtils.java aSmack would return a wrong elementName and namespace, thus choosing a wrong iq provider to parse the response.
From documentation:
http://www.igniterealtime.org/builds/smack/docs/latest/javadoc/org/jivesoftware/smack/provider/IQProvider.html
At the end of the method call, the parser must be positioned on
the closing tag of the child element.
Just if somebody is trying to do the same, I found what was the problem.
The while condition on the vCard_IQProvider class is wrong, it should be:
while(!done && parser.next() != XmlPullParser.END_DOCUMENT)
Otherwise when done is set to true, the while will check again the condition and move the parser to the next element (with the call parser.next()).

How to pass String array to webservice using ksoap2?

I am having a Web Client in Android using ksoap2 but I can't pass the string array as a parameter to the webservice.
Here's my code
String[] items={"hello","world"};
request.addproperty("str",items);
First use "soapUI" to see correct request structure(like item names,item namespaces , ...).
We assume that you want to write like this XML in request:(here n0 and n1 are namespaces)
<n0:strarray xmlns:n0="http://n0 ..." xmlns:n1="http://n1 ...">
<n1:string>hello</n1:string>
<n1:string>world</n1:string>
</n0:strarray>
extend a class from vector:
import java.util.Hashtable;
import java.util.Vector;
import org.ksoap2.serialization.KvmSerializable;
import org.ksoap2.serialization.PropertyInfo;
public class StringArraySerializer extends Vector<String> implements KvmSerializable {
//n1 stores item namespaces:
String n1 = "http://n1 ...";
#Override
public Object getProperty(int arg0) {
return this.get(arg0);
}
#Override
public int getPropertyCount() {
return this.size();
}
#Override
public void getPropertyInfo(int arg0, Hashtable arg1, PropertyInfo arg2) {
arg2.setName = "string";
arg2.type = PropertyInfo.STRING_CLASS;
arg2.setNamespace = n1;
}
#Override
public void setProperty(int arg0, Object arg1) {
this.add(arg1.toString());
}
}
To build the request you have to do this:
1-make a new Vector-Object from this class:
StringArraySerializer stringArray = new StringArraySerializer();
2-then you can add elements:
stringArray.add("hello");
stringArray.add("world");
3-then you create a PropertyInfo with it:
//n0 stores array namespace:
String n0 = "http://n0 ...";
stringArrayProperty = new PropertyInfo();
stringArrayProperty.setName("strarray");
stringArrayProperty.setValue(stringArray);
stringArrayProperty.setType(stringArray.getClass());
stringArrayProperty.setNamespace(n0);
4-then you add all the properties to the request:
Request = new SoapObject(NAMESPACE, METHOD_NAME);
Request.addProperty(stringArrayProperty);
Reference:
ksoap2-android,CodingTipsAndTricks
it is like that you shold add it one by one.
public class ExtendedSoapObject extends SoapObject
{
public ExtendedSoapObject(String namespace, String name)
{
super(namespace, name);
}
public ExtendedSoapObject(SoapObject o)
{
super(o.getNamespace(), o.getName());
for (int i = 0; i < o.getAttributeCount(); i++)
{
AttributeInfo ai = new AttributeInfo();
o.getAttributeInfo(i, ai);
ai.setValue(o.getAttribute(i));
addAttribute(ai);
}
for (int i = 0; i < o.getPropertyCount(); i++)
{
PropertyInfo pi = new PropertyInfo();
o.getPropertyInfo(i, pi);
pi.setValue(o.getProperty(i));
addProperty(pi);
}
}
#Override
public SoapObject addProperty(String name, Object value)
{
if (value instanceof Object[])
{
Object[] subValues = (Object[]) value;
for (int i = 0; i < subValues.length; i++)
{
super.addProperty(name, subValues[i]);
}
}
else
{
super.addProperty(name, value);
}
return this;
}
#Override
public Object getProperty(String name)
{
List<Object> result = new ArrayList<Object>();
for (int i = 0; i < properties.size(); i++)
{
PropertyInfo prop = (PropertyInfo) properties.elementAt(i);
if (prop.getName() != null && prop.getName().equals(name))
{
result.add(unwrap(prop));
}
}
if (result.size() == 1)
{
return result.get(0);
}
else if (result.size() > 1)
{
return result.toArray(new Object[0]);
}
else
{
return null;
}
}
public Object[] getArrayProperty(String name)
{
Object o = getProperty(name);
Object values[] = null;
if (o != null)
{
if (o instanceof Object[])
{
values = (Object[]) o;
}
else
{
values = new Object[1];
values[0] = o;
}
}
return values;
}
Object unwrap(Object o)
{
if (o instanceof PropertyInfo)
{
return unwrap(((PropertyInfo) o).getValue());
}
else if (o instanceof SoapPrimitive || o instanceof SoapObject)
{
return o;
}
return null;
}
}

Categories

Resources