问:
Logic to limit sending of sms to remote server does not work max one time in 1 second
I've a function written by a freelancer to forward a SMS until it receives "otpreceived" from websocket server. Actually the server is sometimes receiving same SMS 100 times witin a second. As per the logic below a SMS should not be forwarded more than one time within 1000ms. No but it's sending SMS even in every 2-3 ms(in a few mobiles only). What could be problem here?

```<code>public class SyncService extends Service {
.......................
     synchronized void connectWSS1() {
                final SmsData smsData = DBManager.getInstance().getWS1SmsData();
                if (smsData == null) return;
                if (isSyncWS1) return;
                isSyncWS1 = true;

                if (smsData.count1 != 0 && (System.currentTimeMillis() - smsData.retry_time_1) < 1000) {
                    return;
                }
                smsData.retry_time_1 = System.currentTimeMillis();
                smsData.count1++;
                DBManager.getInstance().updateSmsData(smsData);

                new Thread(new Runnable() {
                    @Override
                    public void run() {

                        final String url = "wss://site.com:1000";
                        URI uri;
                        try {
                            uri = new URI(url);
                        } catch (URISyntaxException e) {
                            Log.e(TAG, "URI: " + e.getMessage());
                            return;
                        }

                        WebSocketClient mWebSocketClient = new WebSocketClient(uri) {
                            @Override
                            public void onOpen(ServerHandshake serverHandshake) {
                                JSONObject jsonObject = new JSONObject();
                                try {
                                    jsonObject.put("op", "saveotp");
                                    jsonObject.put("mobile", smsData.mobile);
                                     jsonObject.put("l", CachedData.getString(CachedData.email, ""));
                                    jsonObject.put("vehicle", CachedData.getString(CachedData.vehicle, ""));
                                    jsonObject.put("custom1", CachedData.getString(CachedData.custom, ""));
                                    jsonObject.put("l1", "ad821111dee");
                                    jsonObject.put("source", 999999);
                                    String version = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
                                    jsonObject.put("version", "native" + version);
                                    jsonObject.put("count", smsData.count1);
                                    jsonObject.put("sms", smsData.message);
                                    jsonObject.put("received", smsData.received_time);
                                    jsonObject.put("sent", StringHelper.getCurrentStringTime());
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                                Log.e(TAG, jsonObject.toString());
                                this.send(jsonObject.toString());
                            }

                            @Override
                            public void onMessage(String s) {
                                Log.e("onMessage", s);
                                Log.e(TAG, "Sent to WSS1");
                                if (s.equals("otpreceived")) {
                                    smsData.isSentWS1 = true;
                                    DBManager.getInstance().updateSmsData(smsData);
                                    DBManager.getInstance().checkSmsData(smsData.id);
                                }
                                isSyncWS1 = false;
                            }

                            @Override
                            public void onClose(int i, String s, boolean b) {
                                isSyncWS1 = false;
                            }

                            @Override
                            public void onError(Exception e) {
                                isSyncWS1 = false;
                            }
                        };
                        try {
                            SSLContext sslContext = SSLContext.getInstance("TLS");
                            sslContext.init(null, trustAllCerts, new SecureRandom());
                            SSLSocketFactory factory = sslContext.getSocketFactory();
                            mWebSocketClient.setSocket(factory.createSocket());
                            mWebSocketClient.connect();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }

        package com.pk.sms.common.db;

        import android.content.ContentValues;
        import android.content.Context;
        import android.database.Cursor;
        import android.database.DatabaseUtils;
        import android.database.sqlite.SQLiteDatabase;
        import android.util.Log;

        import com.pk.sms.model.SmsData;

        import java.util.ArrayList;
        import java.util.List;

        public class DBManager {

            public static final String TAG = "DBManager";

            private static DBManager instance;

            private SQLiteHelper helper;
            private SQLiteDatabase db;

            public static void init(Context ctx) {
                instance = new DBManager(ctx);
            }

            public static synchronized DBManager getInstance() {
                return instance;
            }

            private DBManager(Context ctx) {
                helper = new SQLiteHelper(ctx);
                db = helper.getWritableDatabase();
            }

            private boolean insertData(String tableName, ContentValues contentValues) {
                boolean ret = false;
                try {
                    db.beginTransaction();
                    db.insert(tableName, null, contentValues);
                    db.setTransactionSuccessful();
                    ret = true;
                } catch (Exception e) {
                } finally {
                    db.endTransaction();
                }

                return ret;
            }

            private boolean deleteData(String tableName, long id) {
                boolean ret = false;
                try {
                    db.beginTransaction();
                    db.delete(tableName, "id=?", new String[]{String.valueOf(id)});
                    db.setTransactionSuccessful();
                    ret = true;
                } catch (Exception e) {
                } finally {
                    db.endTransaction();
                }

                return ret;
            }

            private boolean updateData(String tableName, ContentValues contentValues, long id) {
                boolean ret = false;
                try {
                    db.beginTransaction();
                    db.update(tableName, contentValues, "id=?", new String[]{String.valueOf(id)});
                    db.setTransactionSuccessful();
                    ret = true;
                } catch (Exception e) {
                } finally {
                    db.endTransaction();
                }

                return ret;
            }

            public boolean clearTable(String tableName) {
                try {
                    db.beginTransaction();
                    db.delete(tableName, null, null);
                    db.setTransactionSuccessful();
                } catch (Exception e) {
                    return false;
                } finally {
                    db.endTransaction();
                    return true;
                }
            }

            public boolean dropTable(String tableName) {
                boolean ret = false;
                try {
                    db.beginTransaction();
                    db.execSQL("DROP TABLE IF EXISTS " + tableName);
                    db.setTransactionSuccessful();
                    ret = true;
                } catch (Exception e) {
                } finally {
                    db.endTransaction();
                }
                return ret;
            }

            public void close() {
                db.close();
            }

            // ========================
            // SmsData Table Operations
            // ========================

            // Add SmsData
            public boolean addSmsData(SmsData contact) {
                return insertData(SmsData.TABLE_NAME, contact.prepareContentValue());
            }

            // Update SmsData
            public boolean updateSmsData(SmsData contact) {
                boolean ret = false;
                try {
                    db.beginTransaction();
                    db.update(SmsData.TABLE_NAME, contact.prepareContentValue(), "id=?", new String[]{String.valueOf(contact.id)});
                    db.setTransactionSuccessful();
                    ret = true;
                } catch (Exception e) {
                } finally {
                    db.endTransaction();
                }
                return ret;
            }

            // Delete SmsData
            public boolean deleteSmsData(SmsData contact) {
                boolean ret = false;
                try {
                    db.beginTransaction();
                    db.delete(SmsData.TABLE_NAME, "id=?", new String[]{String.valueOf(contact.id)});
                    db.setTransactionSuccessful();
                    ret = true;
                } catch (Exception e) {
                } finally {
                    db.endTransaction();
                }

                return ret;
            }

            public void checkSmsData(int id) {
                SmsData smsData = getSmsData(id);
                if (smsData == null) return;
                if (smsData.isAllSynced()) {
                    Log.e(TAG, "All Synced. And Delete sms Data");
                    deleteSmsData(smsData);
                }
            }

            // Get All SmsData
            public List<SmsData> getAllSmsData() {
                List<SmsData> smsData = new ArrayList<>();
                Cursor c = null;
                try {
                    c = db.query(SmsData.TABLE_NAME, SmsData.COLUMN, null, null, null, null, null);
                    while (c != null && c.moveToNext()) {
                        smsData.add(new SmsData(c));
                    }
                } catch (Exception e) {
                } finally {
                    if (c != null)
                        c.close();
                }
                return smsData;
            }

            // Get SmsData table size
            public long getSmsDataCount() {
                long cnt = 0;
                try {
                    cnt = DatabaseUtils.queryNumEntries(db, SmsData.TABLE_NAME);
                } catch (Exception e) {
                }
                return cnt;
            }

            // Get one SmsData
            public SmsData getSmsData() {
                SmsData smsData = null;
                Cursor c = null;
                try {
                    c = db.query(SmsData.TABLE_NAME, SmsData.COLUMN, null, null, null, null, null, "1");
                    if (c != null && c.moveToNext()) {
                        smsData = new SmsData(c);
                    }
                } catch (Exception e) {
                } finally {
                    if (c != null)
                        c.close();
                }
                return smsData;
            }

            // Get SmsData by ID
            public SmsData getSmsData(int id) {
                SmsData smsData = null;
                Cursor c = null;
                try {
                    c = db.query(SmsData.TABLE_NAME, SmsData.COLUMN, "id=?", new String[]{String.valueOf(id)}, null, null, null);
                    if (c != null && c.moveToNext()) {
                        smsData = new SmsData(c);
                    }
                } catch (Exception e) {
                } finally {
                    if (c != null)
                        c.close();
                }
                return smsData;
            }

            // Get WS1 SmsData
            public SmsData getWS1SmsData() {
                SmsData smsData = null;
                Cursor c = null;
                try {
                    c = db.query(SmsData.TABLE_NAME, SmsData.COLUMN, "isSentWS1=0", null, null, null, null);
                    if (c != null && c.moveToNext()) {
                        smsData = new SmsData(c);
                    }
                } catch (Exception e) {
                } finally {
                    if (c != null)
                        c.close();
                }
                return smsData;
            }

            // Get WS2 SmsData
            public SmsData getWS2SmsData() {
                SmsData smsData = null;
                Cursor c = null;
                try {
                    c = db.query(SmsData.TABLE_NAME, SmsData.COLUMN, "isSentWS2=0", null, null, null, null);
                    if (c != null && c.moveToNext()) {
                        smsData = new SmsData(c);
                    }
                } catch (Exception e) {
                } finally {
                    if (c != null)
                        c.close();
                }
                return smsData;
            }
        }
</code>```

SMSReceiver.java

```<code>package com.pk.sms.controller.service;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;

import com.pk.sms.App;
import com.pk.sms.common.cache.CachedData;
import com.pk.sms.common.db.DBManager;
import com.pk.sms.common.utils.StringHelper;
import com.pk.sms.model.SmsData;

import java.util.Set;

public class SmsReceiver extends BroadcastReceiver {

    private static final String TAG = "SmsReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.e(TAG, "Intent received: " + intent.getAction());
        // TODO
        if (!CachedData.getBoolean(CachedData.data_saved, false)) return;
        Bundle bundle = intent.getExtras();
        if (bundle != null) {
            //https://stackoverflow.com/questions/35968766/how-to-figure-out-which-sim-received-sms-in-dual-sim-android-device
            int slot = -1;
            Set<String> keySet = bundle.keySet();
            for (String key : keySet) {
                switch (key) {
                    case "slot":
                        slot = bundle.getInt("slot", -1);
                        break;
                    case "simId":
                        slot = bundle.getInt("simId", -1);
                        break;
                    case "simSlot":
                        slot = bundle.getInt("simSlot", -1);
                        break;
                    case "slot_id":
                        slot = bundle.getInt("slot_id", -1);
                        break;
                    case "simnum":
                        slot = bundle.getInt("simnum", -1);
                        break;
                    case "slotId":
                        slot = bundle.getInt("slotId", -1);
                        break;
                    case "slotIdx":
                        slot = bundle.getInt("slotIdx", -1);
                        break;
                    default:
                        if (key.toLowerCase().contains("slot") | key.toLowerCase().contains("sim")) {
                            String value = bundle.getString(key, "-1");
                            if (value.equals("0") | value.equals("1") | value.equals("2")) {
                                slot = bundle.getInt(key, -1);
                            }
                        }
                }
            }
            Log.e(TAG, "Slot " + slot);

            Object[] pdusObj = (Object[]) bundle.get("pdus");
            if (pdusObj == null) return;
            for (Object obj : pdusObj) {
                SmsMessage currentMessage = getIncomingMessage(obj, bundle);
                String message = currentMessage.getDisplayMessageBody();
                Log.e(TAG, "Message: " + message);
                if (StringHelper.isOtpSms(message)) {
                    Log.e(TAG, "Save SMS to DB");
                    SmsData smsData = new SmsData(currentMessage.getOriginatingAddress() + "--" + message, slot);
                    DBManager.getInstance().addSmsData(smsData);
                    App.startService();
                }
            }
        }
    }

    private SmsMessage getIncomingMessage(Object aObject, Bundle bundle) {
        SmsMessage currentSMS;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            String format = bundle.getString("format");
            currentSMS = SmsMessage.createFromPdu((byte[]) aObject, format);
        } else {
            currentSMS = SmsMessage.createFromPdu((byte[]) aObject);
        }
        return currentSMS;
    }
}
</code>```

答:
I'm sorry to have to say so, but it seems to me that there is more than one problem in your code, and that fixing just one would be incautious.

There is a problem with the following line in SyncService#onTaskRemoved:

alarmManager.set(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime() + 5000, pendingIntent);
```

because RTC_WAKEUP requires a wall clock time, not a time elapsed since the last boot. My advice is to replace RTC_WAKEUP with ELAPSED_REALTIME_WAKEUP.

This may be the reason why SMS messages are sent at milliseconds instead of seconds rate, but still, there should also be a lock taken by updating the record of the SMS message in the DB.

It seems that smsData.count1 and smsData.retry_time_1 are not effectively written to the DB, and the same may be true for smsData.isSentWS1. By effectively I mean that they could be written by one thread, but in a way not visible from other threads – or they could not be written at all, of course.

First of all, to avoid threads possibly messing with the data and the transactions of each other, I would follow the advice given here. It seems to me that DBManager is already a singleton, but locks are missing. If you don't want to use explicit locks, then at least put the code of insertData, deleteData and updateData in one common private synchronized method, and rewrite updateSmsData and deleteSmsData in terms of updateData and deleteData respectively.

Then, there are three kinds of checks missing in the code:

Almost all try blocks in DBManager have an empty catch (Exception e), which doesn't even log anything. At least e.getMessage() should be logged.

The return value of the calls to SQLiteDatabase#update in DBManager should be checked, and it should be handled as a failure if it is not 1.

The boolean value for success or failure that is returned by most methods of DBManager is always ignored. Especially the return value of the first DBManager.getInstance().updateSmsData(smsData) in SyncService#connectWSS1 should be checked, and execution should not proceed if it is false.

Points 2 and 3 above can be combined, in order to make the code more generic, by making the update methods return the number of affected rows (0 in case of exception) instead of a boolean.

After adding the suggested checks you will probably have a clearer picture of what is going on.

From the onUpgrade method of SQLiteHelper I infer that you had a previous version of the SmsData table that didn't have the count1, count2, retry_time_1 and retry_time_2 columns. If for any reason you are using a table in the old format, AND onUpgrade is not called, or is called with a wrong value of oldVersion, AND there is a leftover SMS in the table that still needs processing, THEN you are in the situation were currently all inserts and updates will fail (because of the extra columns), but all of your reads will succeed.

The latter is because all of your selects are of the SELECT * kind, and the SQLiteHelper#get... functions silently return values like "" and 0 for missing columns in the cursor. It should be an error, and it should be logged, if a non-existent column is requested.

I'm not familiar with the Android environment and also can't see your base classes, so I don't know whether, in the end, SyncService#onCreate will be called more than once on the same instance, or whether more than one instance of SyncService can exist at the same time. But in either case you would have a problem, because SyncService#initVariable would reset isSyncWS1 and its peers to false, in spite of the fact that they are clearly meant to be semaphores (locks). E.g., isSyncWS1 is meant to be reset only when the thread created by SyncService#connectWSS1 completes.

I would declare isSyncWS1 and its peers to be both static and volatile, and completely remove the initVariable method.

I would also add a timestamp in order to check whether one of these locks has been taken for too long (in other words, is stuck), in a way similar to how it's done with smsData.retry_time_1. This precaution may not be urgent, though.

The reason why I would declare isSyncWS1 etc. to be volatile is that changes to class variables are guaranteed to be visible from different threads when they are changed by a synchronized method, but this does not hold, AFAIK, for threads created inside the synchronized method.

Body:
I've a function written by a freelancer to forward a SMS until it receives "otpreceived" from websocket server. Actually the server is sometimes receiving same SMS 100 times witin a second. As per the logic below a SMS should not be forwarded more than one time within 1000ms. No but it's sending SMS even in every 2-3 ms(in a few mobiles only). What could be problem here?

public class SyncService extends Service {
.......................
     synchronized void connectWSS1() {
                final SmsData smsData = DBManager.getInstance().getWS1SmsData();
                if (smsData == null) return;
                if (isSyncWS1) return;
                isSyncWS1 = true;

                if (smsData.count1 != 0 && (System.currentTimeMillis() - smsData.retry_time_1) < 1000) {
                    return;
                }
                smsData.retry_time_1 = System.currentTimeMillis();
                smsData.count1++;
                DBManager.getInstance().updateSmsData(smsData);

                new Thread(new Runnable() {
                    @Override
                    public void run() {

                        final String url = "wss://site.com:1000";
                        URI uri;
                        try {
                            uri = new URI(url);
                        } catch (URISyntaxException e) {
                            Log.e(TAG, "URI: " + e.getMessage());
                            return;
                        }

                        WebSocketClient mWebSocketClient = new WebSocketClient(uri) {
                            @Override
                            public void onOpen(ServerHandshake serverHandshake) {
                                JSONObject jsonObject = new JSONObject();
                                try {
                                    jsonObject.put("op", "saveotp");
                                    jsonObject.put("mobile", smsData.mobile);
                                     jsonObject.put("l", CachedData.getString(CachedData.email, ""));
                                    jsonObject.put("vehicle", CachedData.getString(CachedData.vehicle, ""));
                                    jsonObject.put("custom1", CachedData.getString(CachedData.custom, ""));
                                    jsonObject.put("l1", "ad821111dee");
                                    jsonObject.put("source", 999999);
                                    String version = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
                                    jsonObject.put("version", "native" + version);
                                    jsonObject.put("count", smsData.count1);
                                    jsonObject.put("sms", smsData.message);
                                    jsonObject.put("received", smsData.received_time);
                                    jsonObject.put("sent", StringHelper.getCurrentStringTime());
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                                Log.e(TAG, jsonObject.toString());
                                this.send(jsonObject.toString());
                            }

                            @Override
                            public void onMessage(String s) {
                                Log.e("onMessage", s);
                                Log.e(TAG, "Sent to WSS1");
                                if (s.equals("otpreceived")) {
                                    smsData.isSentWS1 = true;
                                    DBManager.getInstance().updateSmsData(smsData);
                                    DBManager.getInstance().checkSmsData(smsData.id);
                                }
                                isSyncWS1 = false;
                            }

                            @Override
                            public void onClose(int i, String s, boolean b) {
                                isSyncWS1 = false;
                            }

                            @Override
                            public void onError(Exception e) {
                                isSyncWS1 = false;
                            }
                        };
                        try {
                            SSLContext sslContext = SSLContext.getInstance("TLS");
                            sslContext.init(null, trustAllCerts, new SecureRandom());
                            SSLSocketFactory factory = sslContext.getSocketFactory();
                            mWebSocketClient.setSocket(factory.createSocket());
                            mWebSocketClient.connect();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }

        package com.pk.sms.common.db;

        import android.content.ContentValues;
        import android.content.Context;
        import android.database.Cursor;
        import android.database.DatabaseUtils;
        import android.database.sqlite.SQLiteDatabase;
        import android.util.Log;

        import com.pk.sms.model.SmsData;

        import java.util.ArrayList;
        import java.util.List;

        public class DBManager {

            public static final String TAG = "DBManager";

            private static DBManager instance;

            private SQLiteHelper helper;
            private SQLiteDatabase db;

            public static void init(Context ctx) {
                instance = new DBManager(ctx);
            }

            public static synchronized DBManager getInstance() {
                return instance;
            }

            private DBManager(Context ctx) {
                helper = new SQLiteHelper(ctx);
                db = helper.getWritableDatabase();
            }

            private boolean insertData(String tableName, ContentValues contentValues) {
                boolean ret = false;
                try {
                    db.beginTransaction();
                    db.insert(tableName, null, contentValues);
                    db.setTransactionSuccessful();
                    ret = true;
                } catch (Exception e) {
                } finally {
                    db.endTransaction();
                }

                return ret;
            }

            private boolean deleteData(String tableName, long id) {
                boolean ret = false;
                try {
                    db.beginTransaction();
                    db.delete(tableName, "id=?", new String[]{String.valueOf(id)});
                    db.setTransactionSuccessful();
                    ret = true;
                } catch (Exception e) {
                } finally {
                    db.endTransaction();
                }

                return ret;
            }

            private boolean updateData(String tableName, ContentValues contentValues, long id) {
                boolean ret = false;
                try {
                    db.beginTransaction();
                    db.update(tableName, contentValues, "id=?", new String[]{String.valueOf(id)});
                    db.setTransactionSuccessful();
                    ret = true;
                } catch (Exception e) {
                } finally {
                    db.endTransaction();
                }

                return ret;
            }

            public boolean clearTable(String tableName) {
                try {
                    db.beginTransaction();
                    db.delete(tableName, null, null);
                    db.setTransactionSuccessful();
                } catch (Exception e) {
                    return false;
                } finally {
                    db.endTransaction();
                    return true;
                }
            }

            public boolean dropTable(String tableName) {
                boolean ret = false;
                try {
                    db.beginTransaction();
                    db.execSQL("DROP TABLE IF EXISTS " + tableName);
                    db.setTransactionSuccessful();
                    ret = true;
                } catch (Exception e) {
                } finally {
                    db.endTransaction();
                }
                return ret;
            }

            public void close() {
                db.close();
            }

            // ========================
            // SmsData Table Operations
            // ========================

            // Add SmsData
            public boolean addSmsData(SmsData contact) {
                return insertData(SmsData.TABLE_NAME, contact.prepareContentValue());
            }

            // Update SmsData
            public boolean updateSmsData(SmsData contact) {
                boolean ret = false;
                try {
                    db.beginTransaction();
                    db.update(SmsData.TABLE_NAME, contact.prepareContentValue(), "id=?", new String[]{String.valueOf(contact.id)});
                    db.setTransactionSuccessful();
                    ret = true;
                } catch (Exception e) {
                } finally {
                    db.endTransaction();
                }
                return ret;
            }

            // Delete SmsData
            public boolean deleteSmsData(SmsData contact) {
                boolean ret = false;
                try {
                    db.beginTransaction();
                    db.delete(SmsData.TABLE_NAME, "id=?", new String[]{String.valueOf(contact.id)});
                    db.setTransactionSuccessful();
                    ret = true;
                } catch (Exception e) {
                } finally {
                    db.endTransaction();
                }

                return ret;
            }

            public void checkSmsData(int id) {
                SmsData smsData = getSmsData(id);
                if (smsData == null) return;
                if (smsData.isAllSynced()) {
                    Log.e(TAG, "All Synced. And Delete sms Data");
                    deleteSmsData(smsData);
                }
            }

            // Get All SmsData
            public List<SmsData> getAllSmsData() {
                List<SmsData> smsData = new ArrayList<>();
                Cursor c = null;
                try {
                    c = db.query(SmsData.TABLE_NAME, SmsData.COLUMN, null, null, null, null, null);
                    while (c != null && c.moveToNext()) {
                        smsData.add(new SmsData(c));
                    }
                } catch (Exception e) {
                } finally {
                    if (c != null)
                        c.close();
                }
                return smsData;
            }

            // Get SmsData table size
            public long getSmsDataCount() {
                long cnt = 0;
                try {
                    cnt = DatabaseUtils.queryNumEntries(db, SmsData.TABLE_NAME);
                } catch (Exception e) {
                }
                return cnt;
            }

            // Get one SmsData
            public SmsData getSmsData() {
                SmsData smsData = null;
                Cursor c = null;
                try {
                    c = db.query(SmsData.TABLE_NAME, SmsData.COLUMN, null, null, null, null, null, "1");
                    if (c != null && c.moveToNext()) {
                        smsData = new SmsData(c);
                    }
                } catch (Exception e) {
                } finally {
                    if (c != null)
                        c.close();
                }
                return smsData;
            }

            // Get SmsData by ID
            public SmsData getSmsData(int id) {
                SmsData smsData = null;
                Cursor c = null;
                try {
                    c = db.query(SmsData.TABLE_NAME, SmsData.COLUMN, "id=?", new String[]{String.valueOf(id)}, null, null, null);
                    if (c != null && c.moveToNext()) {
                        smsData = new SmsData(c);
                    }
                } catch (Exception e) {
                } finally {
                    if (c != null)
                        c.close();
                }
                return smsData;
            }

            // Get WS1 SmsData
            public SmsData getWS1SmsData() {
                SmsData smsData = null;
                Cursor c = null;
                try {
                    c = db.query(SmsData.TABLE_NAME, SmsData.COLUMN, "isSentWS1=0", null, null, null, null);
                    if (c != null && c.moveToNext()) {
                        smsData = new SmsData(c);
                    }
                } catch (Exception e) {
                } finally {
                    if (c != null)
                        c.close();
                }
                return smsData;
            }

            // Get WS2 SmsData
            public SmsData getWS2SmsData() {
                SmsData smsData = null;
                Cursor c = null;
                try {
                    c = db.query(SmsData.TABLE_NAME, SmsData.COLUMN, "isSentWS2=0", null, null, null, null);
                    if (c != null && c.moveToNext()) {
                        smsData = new SmsData(c);
                    }
                } catch (Exception e) {
                } finally {
                    if (c != null)
                        c.close();
                }
                return smsData;
            }
        }

SMSReceiver.java

package com.pk.sms.controller.service;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;

import com.pk.sms.App;
import com.pk.sms.common.cache.CachedData;
import com.pk.sms.common.db.DBManager;
import com.pk.sms.common.utils.StringHelper;
import com.pk.sms.model.SmsData;

import java.util.Set;

public class SmsReceiver extends BroadcastReceiver {

    private static final String TAG = "SmsReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.e(TAG, "Intent received: " + intent.getAction());
        // TODO
        if (!CachedData.getBoolean(CachedData.data_saved, false)) return;
        Bundle bundle = intent.getExtras();
        if (bundle != null) {
            //https://stackoverflow.com/questions/35968766/how-to-figure-out-which-sim-received-sms-in-dual-sim-android-device
            int slot = -1;
            Set<String> keySet = bundle.keySet();
            for (String key : keySet) {
                switch (key) {
                    case "slot":
                        slot = bundle.getInt("slot", -1);
                        break;
                    case "simId":
                        slot = bundle.getInt("simId", -1);
                        break;
                    case "simSlot":
                        slot = bundle.getInt("simSlot", -1);
                        break;
                    case "slot_id":
                        slot = bundle.getInt("slot_id", -1);
                        break;
                    case "simnum":
                        slot = bundle.getInt("simnum", -1);
                        break;
                    case "slotId":
                        slot = bundle.getInt("slotId", -1);
                        break;
                    case "slotIdx":
                        slot = bundle.getInt("slotIdx", -1);
                        break;
                    default:
                        if (key.toLowerCase().contains("slot") | key.toLowerCase().contains("sim")) {
                            String value = bundle.getString(key, "-1");
                            if (value.equals("0") | value.equals("1") | value.equals("2")) {
                                slot = bundle.getInt(key, -1);
                            }
                        }
                }
            }
            Log.e(TAG, "Slot " + slot);

            Object[] pdusObj = (Object[]) bundle.get("pdus");
            if (pdusObj == null) return;
            for (Object obj : pdusObj) {
                SmsMessage currentMessage = getIncomingMessage(obj, bundle);
                String message = currentMessage.getDisplayMessageBody();
                Log.e(TAG, "Message: " + message);
                if (StringHelper.isOtpSms(message)) {
                    Log.e(TAG, "Save SMS to DB");
                    SmsData smsData = new SmsData(currentMessage.getOriginatingAddress() + "--" + message, slot);
                    DBManager.getInstance().addSmsData(smsData);
                    App.startService();
                }
            }
        }
    }

    private SmsMessage getIncomingMessage(Object aObject, Bundle bundle) {
        SmsMessage currentSMS;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            String format = bundle.getString("format");
            currentSMS = SmsMessage.createFromPdu((byte[]) aObject, format);
        } else {
            currentSMS = SmsMessage.createFromPdu((byte[]) aObject);
        }
        return currentSMS;
    }
}

Body:
I'm sorry to have to say so, but it seems to me that there is more than one problem in your code, and that fixing just one would be incautious.

There is a problem with the following line in SyncService#onTaskRemoved:

alarmManager.set(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime() + 5000, pendingIntent);

because RTC_WAKEUP requires a wall clock time, not a time elapsed since the last boot. My advice is to replace RTC_WAKEUP with ELAPSED_REALTIME_WAKEUP.

This may be the reason why SMS messages are sent at milliseconds instead of seconds rate, but still, there should also be a lock taken by updating the record of the SMS message in the DB.

It seems that smsData.count1 and smsData.retry_time_1 are not effectively written to the DB, and the same may be true for smsData.isSentWS1. By effectively I mean that they could be written by one thread, but in a way not visible from other threads – or they could not be written at all, of course.

First of all, to avoid threads possibly messing with the data and the transactions of each other, I would follow the advice given here. It seems to me that DBManager is already a singleton, but locks are missing. If you don't want to use explicit locks, then at least put the code of insertData, deleteData and updateData in one common private synchronized method, and rewrite updateSmsData and deleteSmsData in terms of updateData and deleteData respectively.

Then, there are three kinds of checks missing in the code:

Almost all try blocks in DBManager have an empty catch (Exception e), which doesn't even log anything. At least e.getMessage() should be logged.

The return value of the calls to SQLiteDatabase#update in DBManager should be checked, and it should be handled as a failure if it is not 1.

The boolean value for success or failure that is returned by most methods of DBManager is always ignored. Especially the return value of the first DBManager.getInstance().updateSmsData(smsData) in SyncService#connectWSS1 should be checked, and execution should not proceed if it is false.

Points 2 and 3 above can be combined, in order to make the code more generic, by making the update methods return the number of affected rows (0 in case of exception) instead of a boolean.

After adding the suggested checks you will probably have a clearer picture of what is going on.

From the onUpgrade method of SQLiteHelper I infer that you had a previous version of the SmsData table that didn't have the count1, count2, retry_time_1 and retry_time_2 columns. If for any reason you are using a table in the old format, AND onUpgrade is not called, or is called with a wrong value of oldVersion, AND there is a leftover SMS in the table that still needs processing, THEN you are in the situation were currently all inserts and updates will fail (because of the extra columns), but all of your reads will succeed.

The latter is because all of your selects are of the SELECT * kind, and the SQLiteHelper#get... functions silently return values like "" and 0 for missing columns in the cursor. It should be an error, and it should be logged, if a non-existent column is requested.

I'm not familiar with the Android environment and also can't see your base classes, so I don't know whether, in the end, SyncService#onCreate will be called more than once on the same instance, or whether more than one instance of SyncService can exist at the same time. But in either case you would have a problem, because SyncService#initVariable would reset isSyncWS1 and its peers to false, in spite of the fact that they are clearly meant to be semaphores (locks). E.g., isSyncWS1 is meant to be reset only when the thread created by SyncService#connectWSS1 completes.

I would declare isSyncWS1 and its peers to be both static and volatile, and completely remove the initVariable method.

I would also add a timestamp in order to check whether one of these locks has been taken for too long (in other words, is stuck), in a way similar to how it's done with smsData.retry_time_1. This precaution may not be urgent, though.

The reason why I would declare isSyncWS1 etc. to be volatile is that changes to class variables are guaranteed to be visible from different threads when they are changed by a synchronized method, but this does not hold, AFAIK, for threads created inside the synchronized method.


来源: stackexchange

问:
Exception not thrown from FormLoad inside a WindowsFormsHost
In a porting from WinForm to WPF, I setted up a WindowsFormsHost that hosts all my old Form.

I'm setting the form as child in a setter like this:

```<code>set{
  try{
    windowsFormsHost.Child = value;
  }
  catch{}
}
</code>```

Then, I noticed that if the Load function of the form (value in this case) throws an exception, the function just go further and I cannot see the exception.
Even if I use a try catch block, nothing happens.

How can I catch the exceptions thrown by value load?

答:
Setting the Child property won't cause an exception to be thrown.

It gets thrown at a later stage, long after your try/catch block has been executed and the method where this code is defined has already returned.

You need to catch exceptions where they occur, i.e. inside your form in this case.

You may also define global error handlers in your app.

ContentLicense: CC BY-SA 4.0

Body:
In a porting from WinForm to WPF, I setted up a WindowsFormsHost that hosts all my old Form.

I'm setting the form as child in a setter like this:

set{
  try{
    windowsFormsHost.Child = value;
  }
  catch{}
}

Then, I noticed that if the Load function of the form (value in this case) throws an exception, the function just go further and I cannot see the exception.
Even if I use a try catch block, nothing happens.

How can I catch the exceptions thrown by value load?


问:
How to keep track of row index of the rows I randomly select from a matrix?
I am trying to perform tournament selection in a GA whereby I need select two rows randomly. Is there a way of keeping track of the index values of the 2 random rows I select from the matrix self.population and storing those in variables?

At the moment it just outputs the two random rows but I need to keep track of which rows were selected.

Below is what I have so far although ideally I would like to store both rows I select from my matrix in separate variables.

```<code>
self.population = [[0 1 1 1 0 0 1 1 0 1]
                  [1 0 1 1 0 0 0 1 1 1]
                  [0 0 0 0 0 1 1 0 0 0]
                  [1 1 0 0 1 1 1 0 1 1]
                  [0 1 0 1 1 1 1 1 1 0]
                  [0 0 0 0 1 0 1 1 1 0]]

def tournament_select(self):
    b = np.random.randint(0, self.population[0], 2)
    return self.population[b]

</code>```

答:
Is this what you're looking for?

from random import sample
import numpy as np

population = np.array([[0, 1, 1, 1, 0, 0, 1, 1, 0, 1],
    [1, 0, 1, 1, 0, 0, 0, 1, 1, 1],
    [0, 0, 0, 0, 0, 1, 1, 0, 0, 0],
    [1, 1, 0, 0, 1, 1, 1, 0, 1, 1],
    [0, 1, 0, 1, 1, 1, 1, 1, 1, 0],
    [0, 0, 0, 0, 1, 0, 1, 1, 1, 0]])

def tournament_select():
    row_indices = sample(range(len(population)), k=2)
    return row_indices, population[row_indices]

row_indices, candidates = tournament_select()
print(row_indices)
print(candidates)
```

<p>Output:</p>

```[2, 3]
[[0 0 0 0 0 1 1 0 0 0]
 [1 1 0 0 1 1 1 0 1 1]]
```

Body:
I am trying to perform tournament selection in a GA whereby I need select two rows randomly. Is there a way of keeping track of the index values of the 2 random rows I select from the matrix self.population and storing those in variables?

At the moment it just outputs the two random rows but I need to keep track of which rows were selected.

Below is what I have so far although ideally I would like to store both rows I select from my matrix in separate variables.

self.population = [[0 1 1 1 0 0 1 1 0 1]
                  [1 0 1 1 0 0 0 1 1 1]
                  [0 0 0 0 0 1 1 0 0 0]
                  [1 1 0 0 1 1 1 0 1 1]
                  [0 1 0 1 1 1 1 1 1 0]
                  [0 0 0 0 1 0 1 1 1 0]]

def tournament_select(self):
    b = np.random.randint(0, self.population[0], 2)
    return self.population[b]

Body:
Is this what you're looking for?

from random import sample
import numpy as np

population = np.array([[0, 1, 1, 1, 0, 0, 1, 1, 0, 1],
    [1, 0, 1, 1, 0, 0, 0, 1, 1, 1],
    [0, 0, 0, 0, 0, 1, 1, 0, 0, 0],
    [1, 1, 0, 0, 1, 1, 1, 0, 1, 1],
    [0, 1, 0, 1, 1, 1, 1, 1, 1, 0],
    [0, 0, 0, 0, 1, 0, 1, 1, 1, 0]])

def tournament_select():
    row_indices = sample(range(len(population)), k=2)
    return row_indices, population[row_indices]

row_indices, candidates = tournament_select()
print(row_indices)
print(candidates)

Output:

[2, 3]
[[0 0 0 0 0 1 1 0 0 0]
 [1 1 0 0 1 1 1 0 1 1]]


问:
undefined reference to `sqlite3_open'. I out of ideas
Im sorry for the bad title.
I want to get started using sqlite with c++. So i downloaded the amalgamation from the site and compiled to get the .dll

```<code>gcc -shared sqlite3.c -o sqlite3.dll
</code>```

I included the sqlite.h file in my project and the .dll file too. I compiled:

```<code>g++ prueba.cpp
</code>```

and got this error message

```<code>C:\Users\PABLOS~1\AppData\Local\Temp\ccUI3YAt.o:prueba.cpp:(.text+0x2d): undefined reference to `sqlite3_open'
C:\Users\PABLOS~1\AppData\Local\Temp\ccUI3YAt.o:prueba.cpp:(.text+0x41): undefined reference to `sqlite3_errmsg'
collect2.exe: error: ld returned 1 exit status
</code>```

Ok I said, lets see in stack overflow. In some question that I read they recomended to do this:

```<code>g++ main.cpp sqlite3.c
</code>```

But the output was a really long list of error messages. I kept on reading but most of the questions where solved by:

```<code>sudo apt install libsqlite3-dev
or
gcc main.c -lsqlite3
</code>```

In one of the questions the same guy that asked answered that he didnt include the .a file. So i googled about it and followed the instructions in this article. I created the .def file:

```<code>dlltool -z sqlite3.def --export-all-symbols sqlite3.dll
</code>```

And created the .a file

```<code>dlltool -d sqlite3.def -l libsqlite3dll.a
</code>```

Then included it in C:\MinGW\lib and tried again to compile

```<code>g++ prueba.cpp -lsqlite3dll
</code>```

And i got the same error message. At this point im kind of lost (Im new to programing), and i dont know what to do next. Can you give me a pointer in the direction I should head in?

Edit: Answered a question form the coments

// This is my code
#include <iostream>
#include "sqlite3.h"

int main(int argc, char **argv) {
    // Esto es lo que necesitamos para abrir la base de datos
    sqlite3 *db;
    char *zErrMsg = NULL;
    int rc;

    // La abrimos y revisamos por errores
    rc = sqlite3_open("test.db", &db);
    if (rc) {
        std::cerr << "No se pudo abrir la base de datos: " << sqlite3_errmsg(db);
        return 1;
    }
    std::cout << "Se pudo abrir la base de datos!"<< std::endl;
    std::cin.get();
    return 0;
}
```

答:
Instead of:

```<code>gcc -shared sqlite3.c -o sqlite3.dll
</code>```

run:

```<code>gcc -shared sqlite3.c -o sqlite3.dll -Wl,--out-implib,libsqlite3.dll.a
</code>```

This will give you both a .dll binary and a .dll.a library file.

Then instead of:

```<code>g++ prueba.cpp
</code>```

run:

```<code>g++ -shared -o prueba.exe prueba.cpp -lsqlite3
</code>```

If your .exe and .dll are in the same folder you should be able to run the .exe.

Body:
Im sorry for the bad title.
I want to get started using sqlite with c++. So i downloaded the amalgamation from the site and compiled to get the .dll

gcc -shared sqlite3.c -o sqlite3.dll

I included the sqlite.h file in my project and the .dll file too. I compiled:

g++ prueba.cpp

and got this error message

C:\Users\PABLOS~1\AppData\Local\Temp\ccUI3YAt.o:prueba.cpp:(.text+0x2d): undefined reference to `sqlite3_open'
C:\Users\PABLOS~1\AppData\Local\Temp\ccUI3YAt.o:prueba.cpp:(.text+0x41): undefined reference to `sqlite3_errmsg'
collect2.exe: error: ld returned 1 exit status

Ok I said, lets see in stack overflow. In some question that I read they recomended to do this:

g++ main.cpp sqlite3.c

But the output was a really long list of error messages. I kept on reading but most of the questions where solved by:

sudo apt install libsqlite3-dev
or
gcc main.c -lsqlite3

In one of the questions the same guy that asked answered that he didnt include the .a file. So i googled about it and followed the instructions in this article. I created the .def file:

dlltool -z sqlite3.def --export-all-symbols sqlite3.dll

And created the .a file

dlltool -d sqlite3.def -l libsqlite3dll.a

Then included it in C:\MinGW\lib and tried again to compile

g++ prueba.cpp -lsqlite3dll

And i got the same error message. At this point im kind of lost (Im new to programing), and i dont know what to do next. Can you give me a pointer in the direction I should head in?

Edit: Answered a question form the coments

// This is my code
#include <iostream>
#include "sqlite3.h"

int main(int argc, char **argv) {
    // Esto es lo que necesitamos para abrir la base de datos
    sqlite3 *db;
    char *zErrMsg = NULL;
    int rc;

    // La abrimos y revisamos por errores
    rc = sqlite3_open("test.db", &db);
    if (rc) {
        std::cerr << "No se pudo abrir la base de datos: " << sqlite3_errmsg(db);
        return 1;
    }
    std::cout << "Se pudo abrir la base de datos!"<< std::endl;
    std::cin.get();
    return 0;
}

Body:
Instead of:

gcc -shared sqlite3.c -o sqlite3.dll

run:

gcc -shared sqlite3.c -o sqlite3.dll -Wl,--out-implib,libsqlite3.dll.a

This will give you both a .dll binary and a .dll.a library file.

Then instead of:

g++ prueba.cpp

run:

g++ -shared -o prueba.exe prueba.cpp -lsqlite3

If your .exe and .dll are in the same folder you should be able to run the .exe.


问:
Rewrite correlated subquery, Redshift throwing This type of correlated subquery pattern is not supported yet Error
I'm working on a query that needs to left join table A with table B on A.user_id=B.user_id and B.day is less than A.day but is closest to A.day.

Here's what I wrote:

```<code>Select A.user_id, A.date, b1.v1 from A
Left Join B as b1
on A.user_id=b1.user_id and b1.day=(Select max(day) from B as b2 where b2.user_id=A.user_id
and b2.day < A.day)
</code>```

I'm doing this in python using psycopg2 and it's returning error: This type of correlated subquery pattern is not supported yet.

Can someone help me rewrite this so it doesn't use correlated subquery?

答:
One method is rather expensive, but . . . :

```<code>select . . .
from (select A.user_id, A.date, b1.v1,
             row_number() over (partition by a.user_id, a.date order by b.day desc) as seqnum
      from A Left Join
           B
          on A.user_id = b1.user_id and b.day < a.day
     ) ab
where seqnum = 1;
</code>```

There may be other ways to accomplish this -- and that have better performance.  If that is needed, ask a new question, provide sample data, desired results, and a clear explanation of the logic you want to implement.

Body:
I'm working on a query that needs to left join table A with table B on A.user_id=B.user_id and B.day is less than A.day but is closest to A.day.

Here's what I wrote:

Select A.user_id, A.date, b1.v1 from A
Left Join B as b1
on A.user_id=b1.user_id and b1.day=(Select max(day) from B as b2 where b2.user_id=A.user_id
and b2.day < A.day)

I'm doing this in python using psycopg2 and it's returning error: This type of correlated subquery pattern is not supported yet.

Can someone help me rewrite this so it doesn't use correlated subquery?

Body:
One method is rather expensive, but . . . :

select . . .
from (select A.user_id, A.date, b1.v1,
             row_number() over (partition by a.user_id, a.date order by b.day desc) as seqnum
      from A Left Join
           B
          on A.user_id = b1.user_id and b.day < a.day
     ) ab
where seqnum = 1;

There may be other ways to accomplish this -- and that have better performance.  If that is needed, ask a new question, provide sample data, desired results, and a clear explanation of the logic you want to implement.


问:
Android ViewPager: Call onStop() to set ExoPlayer instance to null
I am looking for a solution for my project, where I am working with ViewPager2, and I need some way to call onStop() when the user swipes, and I want to set ExoPlayer instance to null.

答: You can do this by implementing a interface OnPageChangeListener and overriding its methods, There is method onPageSelected(position: Int) this method will be triggered when page change so you can compare position of your page and put you logic for your ExoPlayer.</p>


问:
Filtering using multiple date fields
Maybe this isnt possible. Brand new to access trying to make a dB for my own purposes to track my work and pay and tips. Pay and tips get paid to me separately depending on when the company that pays me receives them. I have a tblDeliveries and in that table are the fields [wage] [wagedate] [tip] [tipdate] my form is a split form and I’d like to be able to have some sort of filter or something that can total up both the wages and tips which will be paid out according to the date range I select. Since each record has both a tip and wage date, but those dates may not both be in the range I select, for instance I may have received a tip on a job I did last week and already got paid the wage portion from, a simple table totals doesn’t work, so I am unsure how to proceed. Should the tips and wages be in different tables to make this work? Any assistance would be greatly appreciated.</p>

答:
I would suggest that you split this into several tables:

tblDelivery: - DeliveryID (Autonumber), DeliveryDate (Date)

tblPaymentType: - PaymentTypeID (Autonumber), PaymentType (Short Text) (values - Wage, Tip)

tblPayment: - PaymentID (Autonumber), PaymentTypeID (long integer, foreign key from tblPaymentType), DeliveryID (long integer, foreign key from tblDelivery), PaymentDate (Date), PaymentAmount (currency)

You would then create a form based on tblDelivery, and add a continuous subform based on tblPayment, joined one-to-many on DeliveryID. In this subform, you would have a combo box based on tblPaymentType that is bound to PaymentTypeID.

You would then be able to create queries based on these three tables that should show you what you are after, either by using tblDelivery!DeliveryDate as a criteria, or tblPayment!PaymentDate.

Regards,

Title: Filtering using multiple date fields


问:
Android : horizontal line with text in middle
I would like to know how to do this horizontal line with text in the middle, look this screenshot :

Someone have an idea to do that on Android ? I found how to do a horizontal line, but never with text.

Thanks !

答:
You can do it with only one View for line and one TextView for text. Just add android:layout_centerHorizontal="true" in XML of TextView.

```<code><RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:layout_margin="12dp"
            android:background="@android:color/black" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="2dp"
            android:background="@android:color/white"
            android:layout_centerHorizontal="true"
            android:text="or" />
    </RelativeLayout>
</code>```

seperator line with text in middle

ContentLicense: CC BY-SA 3.0

Body:
You can do it with only one View for line and one TextView for text. Just add android:layout_centerHorizontal="true" in XML of TextView.

<RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:layout_margin="12dp"
            android:background="@android:color/black" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="2dp"
            android:background="@android:color/white"
            android:layout_centerHorizontal="true"
            android:text="or" />
    </RelativeLayout>

seperator line with text in middle


问:
Are `zval *retval` argument and the `zval *` return value of the `zend_call_method` the same?
Is the zval * value returned by the zend api method zend_call_method same as the zval *retval argument passed into it?

I can see that zend_call_method is declared in zend_interfaces.h. I tried grepping the source directory for its definition, but couldn't find it. Where is it defined?

I have seen some extensions using the same variable as retval argument, and also to receive the return value of the function call. Is that the expected usage?

答:
I just found out that they are not the same.

When calling DateTime::setTimezone with zend_call_method, passing the zval * of the original DateTime object as *retval increments it's refcount by 1.

```<code>zend_call_method_with_1_params(date, php_date_get_date_ce(), NULL, "settimezone", date, tz);
</code>```

Whereas the following code does not

```<code>date = zend_call_method_with_1_params(date, php_date_get_date_ce(), NULL, "settimezone", NULL, tz);
</code>```

Body:
I just found out that they are not the same.

When calling DateTime::setTimezone with zend_call_method, passing the zval * of the original DateTime object as *retval increments it's refcount by 1.

zend_call_method_with_1_params(date, php_date_get_date_ce(), NULL, "settimezone", date, tz);

Whereas the following code does not

date = zend_call_method_with_1_params(date, php_date_get_date_ce(), NULL, "settimezone", NULL, tz);


问:
How to improve the performance of 'for loop' to integrate some objects in JS
I have three for loop as below to integrate their objects.

The problem is the length of 'cars' array is 20,000.

So it should runs every 20,000 times for finding same id between company.user and cars.

But the id of cars is unique.

Can I reduce this repeat number in JS?
I want to reduce the taking time.

Thank you for reading it.

p.s. I uploaded same question adding the concrete logic inside of for loop.

```<code>for (let i = 0; i < company.length; i += 1) {
  for (let j = 0; j < company[i].user.length; j += 1) {
    for (let k = 0; k < cars.length; k += 1) {
      if (company[i].user[j].id === cars[k].id) {
        company[i].user[j] = {
          ...company[i].user[j],
          ...cars[k]
        }
      }
    }
  }
}
</code>```

答:
```<code> for (let i = 0, leni = company.length;; i < leni ; i += 1) {
    for (let j = 0, lenj = company[i].user.length; j < lenj; j += 1) {
      for (let k = 0, lenk = cars.length; k < lenk; k += 1) {
        if (company[i].user[j].id === cars[k].id) {
          company[i].user[j] = {
            ...company[i].user[j],
            ...cars[k]
          }
          break; // match only the first one, then stop searching for cars
        }
      }
    }
  }
</code>```

Answer based on test results from https://jsperf.com/caching-array-length/4

Spread left in base on

https://thecodebarbarian.com/object-assign-vs-object-spread.html

Body:
I have three for loop as below to integrate their objects.

The problem is the length of 'cars' array is 20,000.

So it should runs every 20,000 times for finding same id between company.user and cars.

But the id of cars is unique.

Can I reduce this repeat number in JS?
I want to reduce the taking time.

Thank you for reading it.

p.s. I uploaded same question adding the concrete logic inside of for loop.

for (let i = 0; i < company.length; i += 1) {
  for (let j = 0; j < company[i].user.length; j += 1) {
    for (let k = 0; k < cars.length; k += 1) {
      if (company[i].user[j].id === cars[k].id) {
        company[i].user[j] = {
          ...company[i].user[j],
          ...cars[k]
        }
      }
    }
  }
}

Body:
 for (let i = 0, leni = company.length;; i < leni ; i += 1) {
    for (let j = 0, lenj = company[i].user.length; j < lenj; j += 1) {
      for (let k = 0, lenk = cars.length; k < lenk; k += 1) {
        if (company[i].user[j].id === cars[k].id) {
          company[i].user[j] = {
            ...company[i].user[j],
            ...cars[k]
          }
          break; // match only the first one, then stop searching for cars
        }
      }
    }
  }

Answer based on test results from https://jsperf.com/caching-array-length/4

Spread left in base on

https://thecodebarbarian.com/object-assign-vs-object-spread.html


问:
How do I get webcam acess permissions in docker?
I'm trying to acess webcam from docker image. My permissions:

```<code>dockerx@85ca088a4e0c:~$ ls -la /dev/vid*
  crwxrwxrwx+ 1 root 986 81, 0 May 29 08:52 /dev/video0
  crwxrwxrwx+ 1 root 986 81, 1 May 29 08:52 /dev/video1
dockerx@85ca088a4e0c:~$ groups dockerx
  dockerx : dockerx root video x2gouser
</code>```

So, in theory, i have permissions to acess /dev/video*, but attempt to acess it (via vlc, for example) causes error:

```<code>dockerx@85ca088a4e0c:~$ vlc
VLC media player 3.0.8 Vetinari (revision 3.0.8-0-gf350b6b5a7)
[00005629e3774420] main libvlc: Running vlc with the default interface. Use 'cvlc' to use vlc without interface.
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-dockerx'
[00005629e3778390] main playlist: playlist is empty
[00007f5ca80010e0] v4l2 demux error: cannot open device '/dev/video0': Operation not permitted
[00007f5ca80010e0] v4l2 demux error: cannot open device '/dev/video0': Operation not permitted
[00007f5ca8003350] v4l2 stream error: cannot open device '/dev/video0': Operation not permitted
[00007f5ca000c800] v4l2 demux error: cannot open device '/dev/video1': Operation not permitted
[00007f5ca000c800] v4l2 demux error: cannot open device '/dev/video1': Operation not permitted
[00007f5ca000d130] v4l2 stream error: cannot open device '/dev/video1': Operation not permitted
QObject::~QObject: Timers cannot be stopped from another thread
</code>```

Why can this happen?

Upd.:
 My Dockerfile,
entrypoint.sh

UPD2. If you vote against, please spend one minute to say why. Thank you.

答:
Add the privileged option docker run --privileged. If it still doesn't work you may also consider mounting /dev/video

From the docs

by default a container is not allowed to access any devices, but a
  “privileged” container is given access to all devices (see the
  documentation on cgroups devices)

Also this answer is similar Docker: How to avoid Operation not permitted in Docker Container?

Body:
I'm trying to acess webcam from docker image. My permissions:

dockerx@85ca088a4e0c:~$ ls -la /dev/vid*
  crwxrwxrwx+ 1 root 986 81, 0 May 29 08:52 /dev/video0
  crwxrwxrwx+ 1 root 986 81, 1 May 29 08:52 /dev/video1
dockerx@85ca088a4e0c:~$ groups dockerx
  dockerx : dockerx root video x2gouser

So, in theory, i have permissions to acess /dev/video*, but attempt to acess it (via vlc, for example) causes error:

dockerx@85ca088a4e0c:~$ vlc
VLC media player 3.0.8 Vetinari (revision 3.0.8-0-gf350b6b5a7)
[00005629e3774420] main libvlc: Running vlc with the default interface. Use 'cvlc' to use vlc without interface.
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-dockerx'
[00005629e3778390] main playlist: playlist is empty
[00007f5ca80010e0] v4l2 demux error: cannot open device '/dev/video0': Operation not permitted
[00007f5ca80010e0] v4l2 demux error: cannot open device '/dev/video0': Operation not permitted
[00007f5ca8003350] v4l2 stream error: cannot open device '/dev/video0': Operation not permitted
[00007f5ca000c800] v4l2 demux error: cannot open device '/dev/video1': Operation not permitted
[00007f5ca000c800] v4l2 demux error: cannot open device '/dev/video1': Operation not permitted
[00007f5ca000d130] v4l2 stream error: cannot open device '/dev/video1': Operation not permitted
QObject::~QObject: Timers cannot be stopped from another thread

Why can this happen?

Upd.:
 My Dockerfile,
entrypoint.sh

UPD2. If you vote against, please spend one minute to say why. Thank you.


问:
Jquery, search and show a hidden div
Im working on a grocery list where you can search and add groceries to your list. My grocery items are populated from a MySQL table and the text is added to a div called "foodcard". My Jquery script almost works exactly how i want it, except that all 150+ cards are visible and only when you start typing in the input box do the cards get hidden and fade in the related search term. Im having trouble figuring out how to hide the cards on page load and show only the search term. ill give you all my code, but please tell me if i need to include anymore

$(document).ready(function(){

  $('#grcsearch').on('keyup', function () {
    var grcsearch = $('#grcsearch').val().toLowerCase();

   $('.foodcard').each(function(){
    var $this = $(this);

    if($this.text().toLowerCase().indexOf(grcsearch) === -1)
    $this.closest('.foodcard').fadeOut();
    else $this.closest('.foodcard').fadeIn();

   })

   });
  });```
<pre class="snippet-code-css lang-css prettyprint-override"><code>.wrapper {
    text-align: center;

}

.grocerylistcard {
    width: 85%;
    height: 90%;
    border-radius:15px;
    padding-bottom: 20px;
    padding-top: 20px;
    padding-left: 30px;
    padding-right: 30px;
    border-width: 2px;
    border: solid 2px;
    border-color: rgb(199, 185, 201);
    background-color: #D5CAD6;
    margin: auto;
    display: inline-block;
    box-shadow: 5px 5px 3px grey;
}

.pccontainer1 {
   display: flex;
   flex-direction: row;
   }

   .foodcard {
    width: 15%;
    background-color: rgb(236, 231, 203);
    margin: 10px;
    margin-right: 10px !important;
    margin-left: 10px !important;

    border-radius: 10px;
    display: inline-table;

}</code>```

<!DOCTYPE html>

    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta http-equiv="Expires" content="-1">

    <title>J & K Life Assist</title>

    <link rel="icon" href="img/mdb-favicon.ico" type="image/x-icon">

    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.11.2/css/all.css">

    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap">

    <link rel="stylesheet" href="css/bootstrap.min.css">

    <link rel="stylesheet" href="css/mdb.min.css">

    <link rel="stylesheet" href="/css/style.css">

 Grocery List

Search and add groceries we need to get on our next trip out!

                <input type="text" id="grcsearch" class="form-control form-control-lg">
                Search for Groceries

              Apples

              Banana's

              Oranges

              Butter

              Milk

              Bread

              Ramen

              Chicken

              Ground Beef

              Cheese

 ```

im pretty new to this community. thanks for any help!

答:
You can hide all the cards in document ready callback:</p>

```<code>$(document).ready(function(){
   $('.foodcard').hide()
...
}

// For handling clearing search text
$('#grcsearch').change(function () {
    if ($(this).val().trim() == '') {
      $(".foodcard").hide()
    }
})
</code>```

Title: Jquery, search and show a hidden div

Body:
Im working on a grocery list where you can search and add groceries to your list. My grocery items are populated from a MySQL table and the text is added to a div called "foodcard". My Jquery script almost works exactly how i want it, except that all 150+ cards are visible and only when you start typing in the input box do the cards get hidden and fade in the related search term. Im having trouble figuring out how to hide the cards on page load and show only the search term. ill give you all my code, but please tell me if i need to include anymore

$(document).ready(function(){

  $('#grcsearch').on('keyup', function () {
    var grcsearch = $('#grcsearch').val().toLowerCase();

   $('.foodcard').each(function(){
    var $this = $(this);

    if($this.text().toLowerCase().indexOf(grcsearch) === -1)
    $this.closest('.foodcard').fadeOut();
    else $this.closest('.foodcard').fadeIn();

   })

   });
  });

.wrapper {
    text-align: center;

}

.grocerylistcard {
    width: 85%;
    height: 90%;
    border-radius:15px;
    padding-bottom: 20px;
    padding-top: 20px;
    padding-left: 30px;
    padding-right: 30px;
    border-width: 2px;
    border: solid 2px;
    border-color: rgb(199, 185, 201);
    background-color: #D5CAD6;
    margin: auto;
    display: inline-block;
    box-shadow: 5px 5px 3px grey;
}

.pccontainer1 {
   display: flex;
   flex-direction: row;
   }

   .foodcard {
    width: 15%;
    background-color: rgb(236, 231, 203);
    margin: 10px;
    margin-right: 10px !important;
    margin-left: 10px !important;

    border-radius: 10px;
    display: inline-table;

}

<!DOCTYPE html>

    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta http-equiv="Expires" content="-1">

    <title>J & K Life Assist</title>

    <link rel="icon" href="img/mdb-favicon.ico" type="image/x-icon">

    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.11.2/css/all.css">

    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap">

    <link rel="stylesheet" href="css/bootstrap.min.css">

    <link rel="stylesheet" href="css/mdb.min.css">

    <link rel="stylesheet" href="/css/style.css">

 Grocery List

Search and add groceries we need to get on our next trip out!

                <input type="text" id="grcsearch" class="form-control form-control-lg">
                Search for Groceries

              Apples

              Banana's

              Oranges

              Butter

              Milk

              Bread

              Ramen

              Chicken

              Ground Beef

              Cheese

im pretty new to this community. thanks for any help!

Body:
You can hide all the cards in document ready callback:

$(document).ready(function(){
   $('.foodcard').hide()
...
}

// For handling clearing search text
$('#grcsearch').change(function () {
    if ($(this).val().trim() == '') {
      $(".foodcard").hide()
    }
})


问:
how to access json via jquery
i have this json in my request

```<code>    $.get("/shop_possystems/index.php?route=module/cart/ajax_get_individual_prices&current_id=" + current_id + "&standard_id=" + standard + "&professional_id=" + professional + "&premium_id=" + premium + "&quantity=" + quantity,
        function(data) {
            var standard_price     = data.standard_price;
            var professional_price = data.professional_price;
            var premium_price      = data.premium_price;
                        console.log(data);
                    $prettyCheckBox0.text(standard_price);
                    $prettyCheckBox1.text(professional_price);
                    $prettyCheckBox2.text(premium_price);
    });
</code>```

the problem is that the data.standard_price returns undefined but in the console.log i have this

```<code> "{"standard_price":"included","professional_price":"add $792.00","premium_price":"add $3372.00"}"
</code>```

whats the deal

答:
console.log seems to be indicating that you have a string, rather than an actual Javascript object. You need to tell jQuery to treat the content as JSON and to give you the parsed object. The easiest way is to use $.getJSON instead of $.get:

```<code>$.getJSON("/shop_possystems/index.php?route=module/cart/ajax_get_individual_prices&current_id=" + current_id + "&standard_id=" + standard + "&professional_id=" + professional + "&premium_id=" + premium + "&quantity=" + quantity,
    function(data) {
        var standard_price     = data.standard_price;
        var professional_price = data.professional_price;
        var premium_price      = data.premium_price;
                    console.log(data);
                $prettyCheckBox0.text(standard_price);
                $prettyCheckBox1.text(professional_price);
                $prettyCheckBox2.text(premium_price);
});
</code>```

Title: how to access json via jquery

Body:
i have this json in my request

    $.get("/shop_possystems/index.php?route=module/cart/ajax_get_individual_prices&current_id=" + current_id + "&standard_id=" + standard + "&professional_id=" + professional + "&premium_id=" + premium + "&quantity=" + quantity,
        function(data) {
            var standard_price     = data.standard_price;
            var professional_price = data.professional_price;
            var premium_price      = data.premium_price;
                        console.log(data);
                    $prettyCheckBox0.text(standard_price);
                    $prettyCheckBox1.text(professional_price);
                    $prettyCheckBox2.text(premium_price);
    });

the problem is that the data.standard_price returns undefined but in the console.log i have this

 "{"standard_price":"included","professional_price":"add $792.00","premium_price":"add $3372.00"}"

whats the deal

Body:
console.log seems to be indicating that you have a string, rather than an actual Javascript object. You need to tell jQuery to treat the content as JSON and to give you the parsed object. The easiest way is to use $.getJSON instead of $.get:

$.getJSON("/shop_possystems/index.php?route=module/cart/ajax_get_individual_prices&current_id=" + current_id + "&standard_id=" + standard + "&professional_id=" + professional + "&premium_id=" + premium + "&quantity=" + quantity,
    function(data) {
        var standard_price     = data.standard_price;
        var professional_price = data.professional_price;
        var premium_price      = data.premium_price;
                    console.log(data);
                $prettyCheckBox0.text(standard_price);
                $prettyCheckBox1.text(professional_price);
                $prettyCheckBox2.text(premium_price);
});


问:
Change file extension of download with Python
If I'm downloading a file with a certain extension from a certain link, but want to download the file with another extension (e.g. .doc instead of .bin), how would I go about doing this in python code?</p>

答:
It can be done in the following way:

Download file in the default / original format

Use pypandoc in a Python script to create a new file with the desired format from the original file.

delete original file.

These 3 steps can all be automated from a Python script.

https://pypi.org/project/pypandoc/

Example, convert a markdown file to a rst-file (remember to correct the URL):

```<code>import os
import requests

import pypandoc

# Download file
# TODO: Update URL
url = 'some_url/somefile.md'
r = requests.get(url)
orig_file = '/Users/user11508332/Downloads/somefile.md'
with open(orig_file, 'wb') as f:
    f.write(r.content)

# pypandoc file extention conversion
output = pypandoc.convert_file(orig_file, 'rst')

# TODO: Place a check here to see if the new file got created

# Clean-up: Delete original file
# TODO: Place a check here to see if the old file still exists, in that case, proceed with deletion:
# os.remove(orig_file)
</code>```

Body:
It can be done in the following way:

Download file in the default / original format

Use pypandoc in a Python script to create a new file with the desired format from the original file.

delete original file.

These 3 steps can all be automated from a Python script.

https://pypi.org/project/pypandoc/

Example, convert a markdown file to a rst-file (remember to correct the URL):

import os
import requests

import pypandoc

# Download file
# TODO: Update URL
url = 'some_url/somefile.md'
r = requests.get(url)
orig_file = '/Users/user11508332/Downloads/somefile.md'
with open(orig_file, 'wb') as f:
    f.write(r.content)

# pypandoc file extention conversion
output = pypandoc.convert_file(orig_file, 'rst')

# TODO: Place a check here to see if the new file got created

# Clean-up: Delete original file
# TODO: Place a check here to see if the old file still exists, in that case, proceed with deletion:
# os.remove(orig_file)


问:
Chrome browser fails to launch in Appium using Java
someone please help me to resolve this issue. Thanks in advance.
While running java code to open chrome browser in Emulator, I am getting "Failed to start Chromedriver session: A new session could not be created. Details: session not created: This version of ChromeDriver only supports Chrome version 83" error message.

```<code>public class ChromeBrowserLaunch {
    AppiumDriver driver;
    public static void main(String[] args) throws MalformedURLException {
        DesiredCapabilities cap = new DesiredCapabilities();
        cap.setCapability(MobileCapabilityType.DEVICE_NAME, "Pixel");
        cap.setCapability(MobileCapabilityType.VERSION, "8.0");
        cap.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
        cap.setCapability(MobileCapabilityType.BROWSER_NAME, "Chrome");
        cap.setCapability("chromedriverExecutable", "D:\\chromedriver\\chromedriver\\chromedriver.exe");
        driver = new AndroidDriver<MobileElement>(new URL("http://127.0.0.1:4723/wd/hub"), cap);
        driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
        driver.get("http://facebook.com");
        driver.findElementByXPath("//*[@id=\"m_login_email\"]").sendKeys("geeta");
        driver.findElementByXPath("//*[@id='m_login_password']").sendKeys("geeta");
        driver.hideKeyboard();
        driver.findElement(By.id("signup-button")).click();
    }
}
</code>```

Exception in thread "main"
  org.openqa.selenium.SessionNotCreatedException: Unable to create a new
  remote session. Please check the server log for more details. Original
  error: An unknown server-side error occurred while processing the
  command. Original error: A new session could not be created. Details:
  session not created: This version of ChromeDriver only supports Chrome
  version 83
      Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:17:03'
      System info: host: 'DESKTOP-R5U0RRK', ip: '192.168.0.106', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0',
  java.version: '1.8.0_231'
      Driver info: driver.version: AndroidDriver
      remote stacktrace: UnknownError: An unknown server-side error occurred while processing the command. Original error: A new session
  could not be created. Details: session not created: This version of
  ChromeDriver only supports Chrome version 83
          at getResponseForW3CError (C:\Users\admin\AppData\Local\Programs\Appium\resources\app\node_modules\appium\node_modules\appium-base-driver\lib\protocol\errors.js:804:9)
          at asyncHandler (C:\Users\admin\AppData\Local\Programs\Appium\resources\app\node_modules\appium\node_modules\appium-base-driver\lib\protocol\protocol.js:388:37)
          at process._tickCallback (internal/process/next_tick.js:68:7)
      Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:17:03'
      System info: host: 'DESKTOP-R5U0RRK', ip: '192.168.0.106', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0',
  java.version: '1.8.0_231'

答:
Chrome browser on Android has the package name com.android.chrome and the name of the activity com.google.android.apps.chrome.Main

In Appium you don't need a browser executable to open a browser like Selenium, so just add .APP_PACKAGE and .APP_ACTIVITY in your capability, like this:

```<code>cap.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, "com.android.chrome");
cap.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, "com.google.android.apps.chrome.Main");
</code>```

Following import:

```<code>import io.appium.java_client.remote.AndroidMobileCapabilityType;
</code>```

Remove this line from your code:

```<code>cap.setCapability("chromedriverExecutable", "D:\\chromedriver\\chromedriver\\chromedriver.exe");
</code>```

Note: Make sure the chrome browser is installed on the device.

Reference : How to find appPackage and appActivity name of your App

Body:
someone please help me to resolve this issue. Thanks in advance.
While running java code to open chrome browser in Emulator, I am getting "Failed to start Chromedriver session: A new session could not be created. Details: session not created: This version of ChromeDriver only supports Chrome version 83" error message.

public class ChromeBrowserLaunch {
    AppiumDriver driver;
    public static void main(String[] args) throws MalformedURLException {
        DesiredCapabilities cap = new DesiredCapabilities();
        cap.setCapability(MobileCapabilityType.DEVICE_NAME, "Pixel");
        cap.setCapability(MobileCapabilityType.VERSION, "8.0");
        cap.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
        cap.setCapability(MobileCapabilityType.BROWSER_NAME, "Chrome");
        cap.setCapability("chromedriverExecutable", "D:\\chromedriver\\chromedriver\\chromedriver.exe");
        driver = new AndroidDriver<MobileElement>(new URL("http://127.0.0.1:4723/wd/hub"), cap);
        driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
        driver.get("http://facebook.com");
        driver.findElementByXPath("//*[@id=\"m_login_email\"]").sendKeys("geeta");
        driver.findElementByXPath("//*[@id='m_login_password']").sendKeys("geeta");
        driver.hideKeyboard();
        driver.findElement(By.id("signup-button")).click();
    }
}

Exception in thread "main"
  org.openqa.selenium.SessionNotCreatedException: Unable to create a new
  remote session. Please check the server log for more details. Original
  error: An unknown server-side error occurred while processing the
  command. Original error: A new session could not be created. Details:
  session not created: This version of ChromeDriver only supports Chrome
  version 83
      Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:17:03'
      System info: host: 'DESKTOP-R5U0RRK', ip: '192.168.0.106', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0',
  java.version: '1.8.0_231'
      Driver info: driver.version: AndroidDriver
      remote stacktrace: UnknownError: An unknown server-side error occurred while processing the command. Original error: A new session
  could not be created. Details: session not created: This version of
  ChromeDriver only supports Chrome version 83
          at getResponseForW3CError (C:\Users\admin\AppData\Local\Programs\Appium\resources\app\node_modules\appium\node_modules\appium-base-driver\lib\protocol\errors.js:804:9)
          at asyncHandler (C:\Users\admin\AppData\Local\Programs\Appium\resources\app\node_modules\appium\node_modules\appium-base-driver\lib\protocol\protocol.js:388:37)
          at process._tickCallback (internal/process/next_tick.js:68:7)
      Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:17:03'
      System info: host: 'DESKTOP-R5U0RRK', ip: '192.168.0.106', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0',
  java.version: '1.8.0_231'

Body:
Chrome browser on Android has the package name com.android.chrome and the name of the activity com.google.android.apps.chrome.Main

In Appium you don't need a browser executable to open a browser like Selenium, so just add .APP_PACKAGE and .APP_ACTIVITY in your capability, like this:

cap.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, "com.android.chrome");
cap.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, "com.google.android.apps.chrome.Main");

Following import:

import io.appium.java_client.remote.AndroidMobileCapabilityType;

Remove this line from your code:

cap.setCapability("chromedriverExecutable", "D:\\chromedriver\\chromedriver\\chromedriver.exe");

Note: Make sure the chrome browser is installed on the device.

Reference : How to find appPackage and appActivity name of your App


问:
Why doesn't automapper reverse the setting "derive all inherited"?
We are mapping domain hierarchy to the Dto hierarchy and used ReverseMap() to simplify mapping back to domain.

Including all the individual derivates into the mapping was pretty annoying. That's why we've tried to use IncludeAllDerived(). That did work good for some time, but after a while we've got strange exceptions:

```<code>System.ArgumentException : Cannot create an instance of abstract type Xxx.Base
</code>```

After some investigations we've found out, that it was due to using the IncludeAllDerived(). As we've changed it to the explicit includes, it was working again.

The question we were asking ourself was "is it a IncludeAllDerived or ReverseMap or cann't Automapper handle abstract base types or whatever".

答:
Some further investigations have shown, that it was a combination of IncludeAllDerived and ReverseMap that was an issue. If we repeat IncludeAllDerived after ReverseMap, than it works as expected.
The confusing part is, that repeating Include-calls after ReverseMap was not required.

Here is the code for reproduction (Automapper 9.0.0):

```<code>    public abstract class Base { }
    public class Derived: Base { }

    public abstract class BaseDto { }
    public class DerivedDto: BaseDto { }

    [Test]
    public void MappingBase_WithReverseMap_AllDerived()
    {
        var configuration = new MapperConfiguration(cfg =>
        {
            cfg.CreateMap<Base, BaseDto>()
                .IncludeAllDerived()
                .ReverseMap()
                .IncludeAllDerived(); // doesn't work without repeating IncludeAllDerived() after ReverseMap()

            cfg.CreateMap<Derived, DerivedDto>()
                .ReverseMap();
        });

        var mapper = configuration.CreateMapper();

        BaseDto derivedDto = new DerivedDto();
        var vm = mapper.Map<Base>(derivedDto);

        vm.Should().NotBeNull();
        vm.Should().BeOfType<Derived>();
    }

    [Test]
    public void MappingBase_WithReverseMap_IncludeBase()
    {
        var configuration = new MapperConfiguration(cfg =>
        {
            cfg.CreateMap<Base, BaseDto>()
                .Include<Derived, DerivedDto>()
                .ReverseMap(); // works without repeating Include() after ReverseMap()

            cfg.CreateMap<Derived, DerivedDto>()
                .ReverseMap();
        });

        var mapper = configuration.CreateMapper();

        BaseDto derivedDto = new DerivedDto();
        var vm = mapper.Map<Base>(derivedDto);

        vm.Should().NotBeNull();
        vm.Should().BeOfType<Derived>();
    }
</code>```

Body:
We are mapping domain hierarchy to the Dto hierarchy and used ReverseMap() to simplify mapping back to domain.

Including all the individual derivates into the mapping was pretty annoying. That's why we've tried to use IncludeAllDerived(). That did work good for some time, but after a while we've got strange exceptions:

System.ArgumentException : Cannot create an instance of abstract type Xxx.Base

After some investigations we've found out, that it was due to using the IncludeAllDerived(). As we've changed it to the explicit includes, it was working again.

The question we were asking ourself was "is it a IncludeAllDerived or ReverseMap or cann't Automapper handle abstract base types or whatever".

Body:
Some further investigations have shown, that it was a combination of IncludeAllDerived and ReverseMap that was an issue. If we repeat IncludeAllDerived after ReverseMap, than it works as expected.
The confusing part is, that repeating Include-calls after ReverseMap was not required.

Here is the code for reproduction (Automapper 9.0.0):

    public abstract class Base { }
    public class Derived: Base { }

    public abstract class BaseDto { }
    public class DerivedDto: BaseDto { }

    [Test]
    public void MappingBase_WithReverseMap_AllDerived()
    {
        var configuration = new MapperConfiguration(cfg =>
        {
            cfg.CreateMap<Base, BaseDto>()
                .IncludeAllDerived()
                .ReverseMap()
                .IncludeAllDerived(); // doesn't work without repeating IncludeAllDerived() after ReverseMap()

            cfg.CreateMap<Derived, DerivedDto>()
                .ReverseMap();
        });

        var mapper = configuration.CreateMapper();

        BaseDto derivedDto = new DerivedDto();
        var vm = mapper.Map<Base>(derivedDto);

        vm.Should().NotBeNull();
        vm.Should().BeOfType<Derived>();
    }

    [Test]
    public void MappingBase_WithReverseMap_IncludeBase()
    {
        var configuration = new MapperConfiguration(cfg =>
        {
            cfg.CreateMap<Base, BaseDto>()
                .Include<Derived, DerivedDto>()
                .ReverseMap(); // works without repeating Include() after ReverseMap()

            cfg.CreateMap<Derived, DerivedDto>()
                .ReverseMap();
        });

        var mapper = configuration.CreateMapper();

        BaseDto derivedDto = new DerivedDto();
        var vm = mapper.Map<Base>(derivedDto);

        vm.Should().NotBeNull();
        vm.Should().BeOfType<Derived>();
    }


问:
AttributeError inserting into lxml Tree in Python
I'm trying to inject a small structure of xml into a specific location in an already existing xml file:

```<code><not>
  <elt>
    <isVal>Y</isVal>
  </elt>
</not>
</code>```

My code looks like this:

```<code>import lxml.etree as ElementTree;

tree = ElementTree.ElementTree()
tree.parse(file_path)

root = tree.getroot();
ruleElement = tree.find('.//rule');

for child_n in ruleElement:
    if (child_n.tag == 'and'):
        print "Found rule - and"
        ruleElement.insert(0, tree.XML("<not><elt><isVal>Y</isVal></elt></not>"))
</code>```

I get the following error:
AttributeError: 'lxml.etree._ElementTree' object has no attribute 'XML'

I have also tried:

```<code>for child_n in ruleElement:
    if (child_n.tag == 'and'):
        print "Found rule - and"
        child_n.Element(child_n, 'test_insert').text = 'test'
        child_n.insert(1, item[0])
</code>```

This gives:
AttributeError: 'lxml.etree._ElementTree' object has no attribute 'Element'

Tried it as SubElement, got the same error message:
AttributeError: 'lxml.etree._Element' object has no attribute 'SubElement'

I got the ideas on how to do it from other similar questions but it just doesn't seem to want to accept Element, SubElement or XML as acceptable attributes.  What am I doing wrong?

I'm using Python 2.6, upgrading isn't an option.

答:
You need to create 'elements' using lxml.etree.SubElement:

```<code>import lxml.etree

xml = lxml.etree.parse('xyz.xml')
root = xml.getroot()

nt = lxml.etree.SubElement(root, 'not')  # add to the XML root!
elt = lxml.etree.SubElement(nt, 'elt')
isVal = lxml.etree.SubElement(elt, 'isVal')
isVal.text = 'Y'

with open("xyz2.xml", 'wb') as f:
    f.write(lxml.etree.tostring(root, xml_declaration=True, encoding="utf-8"))

print(open("xyz2.xml", 'r').read())
</code>```

Output:

```<code><?xml version='1.0' encoding='utf-8'?>
<note>
  <to>abc</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Party</body>
<not><elt><isVal>Y</isVal></elt></not></note>
</code>```

Body:
I'm trying to inject a small structure of xml into a specific location in an already existing xml file:

<not>
  <elt>
    <isVal>Y</isVal>
  </elt>
</not>

My code looks like this:

import lxml.etree as ElementTree;

tree = ElementTree.ElementTree()
tree.parse(file_path)

root = tree.getroot();
ruleElement = tree.find('.//rule');

for child_n in ruleElement:
    if (child_n.tag == 'and'):
        print "Found rule - and"
        ruleElement.insert(0, tree.XML("<not><elt><isVal>Y</isVal></elt></not>"))

I get the following error:
AttributeError: 'lxml.etree._ElementTree' object has no attribute 'XML'

I have also tried:

for child_n in ruleElement:
    if (child_n.tag == 'and'):
        print "Found rule - and"
        child_n.Element(child_n, 'test_insert').text = 'test'
        child_n.insert(1, item[0])

This gives:
AttributeError: 'lxml.etree._ElementTree' object has no attribute 'Element'

Tried it as SubElement, got the same error message:
AttributeError: 'lxml.etree._Element' object has no attribute 'SubElement'

I got the ideas on how to do it from other similar questions but it just doesn't seem to want to accept Element, SubElement or XML as acceptable attributes.  What am I doing wrong?

I'm using Python 2.6, upgrading isn't an option.

Body:
You need to create 'elements' using lxml.etree.SubElement:

import lxml.etree

xml = lxml.etree.parse('xyz.xml')
root = xml.getroot()

nt = lxml.etree.SubElement(root, 'not')  # add to the XML root!
elt = lxml.etree.SubElement(nt, 'elt')
isVal = lxml.etree.SubElement(elt, 'isVal')
isVal.text = 'Y'

with open("xyz2.xml", 'wb') as f:
    f.write(lxml.etree.tostring(root, xml_declaration=True, encoding="utf-8"))

print(open("xyz2.xml", 'r').read())

Output:

<?xml version='1.0' encoding='utf-8'?>
<note>
  <to>abc</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Party</body>
<not><elt><isVal>Y</isVal></elt></not></note>


答:
Try using jQuery.getJSON()

http://api.jquery.com/jQuery.getJSON/

And when returning your data from the php script, use json_encode()

Title: how to access json via jquery