问:
What is the industry standard in serializing null attributes in REST based services?
Recently there was discussion with my colleague about proper industry standards, in dealing with XML/JSON format resonses, having elements with null values. My view is to ignore/not including the elements in XML and JSON responses, if a particular element has null values. My belief is it would reduce the payload size and lesser bandwidth in transmission.

Where as my colleagues argument is to include all the attributes/elements defined in JSON/XML, whether there is value or not.

So ideally, it is like

```<code><name>John Doe</name>
 vs
<name>John Doe</name>
<DOB/>
</code>```

Similarly

```<code>{
  "name":"John Doe"
}
vs
{
   "name":"John Doe",
   "DOB":null
}
</code>```

What is the correct approach and why ?

Thanks

答: There is probably no right or wrong approach, it depends on the requirements of the application. That's why Newtonsoft or ServiceStack allow you to configure whether or not you wan't to include null values.</p>

Body:
Recently there was discussion with my colleague about proper industry standards, in dealing with XML/JSON format resonses, having elements with null values. My view is to ignore/not including the elements in XML and JSON responses, if a particular element has null values. My belief is it would reduce the payload size and lesser bandwidth in transmission.

Where as my colleagues argument is to include all the attributes/elements defined in JSON/XML, whether there is value or not.

So ideally, it is like

<name>John Doe</name>
 vs
<name>John Doe</name>
<DOB/>

Similarly

{
  "name":"John Doe"
}
vs
{
   "name":"John Doe",
   "DOB":null
}

What is the correct approach and why ?

Thanks


来源: stackexchange

问:
Value is not changing in React-Native-Numeric-Input
I'm making a E-commerce application for my learning purpose. I was using textInput for update quantity in cart page And now I'm using react-native-numeric-input for that.

I'm updating the quantity onChange of react-native-numeric-input, It was working when I tested it normally but when I added my code to update quantity in my database it is not working properply...
here I'm attaching the video of app's abnormal behavior:
Visit link to watch video

this is my code of numeric input component:

```<code><NumericInput
    totalHeight={35}
    totalWidth={80}
    validateOnBlur={false}
    initValue={qtyN}
    separatorWidth={0}
    rounded={true}
    textColor='#2e6153'
    borderColor='#0000'
    inputStyle={{
        backgroundColor: "#fff",
        borderWidth: 1,
        borderColor: '#2e6153',
        borderStyle: 'solid',
    }}
    containerStyle={{
        backgroundColor: '#2e6153',
        borderWidth: 1,
        borderColor: '#2e6153',
        borderStyle: 'solid',
    }}
    iconStyle={{
        color: '#fff',
    }}
    leftButtonBackgroundColor='#2e6153'
    rightButtonBackgroundColor='#2e6153'
    minValue={1}
    maxValue={999}
    onChange={(value) => this.qtyNumHandle(value, data.item.id)}
/>
</code>```

and function I used on onChange:

```<code>qtyNumHandle = async (value, id) => {
    console.log("qtyNum handler");
    console.log(value)
    console.log(id)
    try{
        let user_id = await AsyncStorage.getItem(ID);
        console.log(user_id);
        let updateProduct = await fetch(`http://website.com/api/cart/updatecart?productid=${id}&userid=${user_id}&qty=${value}`, {
            "method": "POST",
            "headers": {
                "cache-control": "no-cache",
            },
        });
        let updateProductRes = await updateProduct.json();
        console.log(updateProductRes);
        this.fetchCartProduct();
    }catch(errors){
        console.log(errors);
    }
}
</code>```

please tell me if I have done something incorrect. And if my code is correct so why this problem is occurring.

答:
Yeah..!! I got the solution.

The problem was I was not using the value prop.

Here is my new code of NumericInput:

```<code><NumericInput
    value={this.state.cartTotal[data.index].qty}
    // above the state I've used is containing the array data of my cart products
    // and I used [data.index] because this NumericInput is in FlatList.
    // so to get the quantity of perticular I used it array[data.index].qty
    totalHeight={35}
    totalWidth={80}
    validateOnBlur={false}
    initValue={this.state.cartTotal[data.index].qty}
    separatorWidth={0}
    rounded={true}
    textColor='#2e6153'
    borderColor='#0000'
    inputStyle={{
        backgroundColor: "#fff",
        borderWidth: 1,
        borderColor: '#2e6153',
        borderStyle: 'solid',
    }}
    containerStyle={{
        backgroundColor: '#2e6153',
        borderWidth: 1,
        borderColor: '#2e6153',
        borderStyle: 'solid',
    }}
    iconStyle={{
        color: '#fff',
    }}
    leftButtonBackgroundColor='#2e6153'
    rightButtonBackgroundColor='#2e6153'
    minValue={1}
    maxValue={999}
    onChange={(value) => this.qtyNumHandle(value, data.item.id)}
/>
</code>```

and here is my function I used on onChange (this has no change):

```<code>qtyNumHandle = async (value, id) => {
    console.log("qtyNum handler");
    console.log(value)
    console.log(id)
    try{
        let user_id = await AsyncStorage.getItem(ID);
        console.log(user_id);
        let updateProduct = await fetch(`http://website.com/api/cart/updatecart?productid=${id}&userid=${user_id}&qty=${value}`, {
            "method": "POST",
            "headers": {
                "cache-control": "no-cache",
            },
        });
        let updateProductRes = await updateProduct.json();
        console.log(updateProductRes);
        this.fetchCartProduct();
    }catch(errors){
        console.log(errors);
    }
}
</code>```

Hope this will help someone else.

ContentLicense: CC BY-SA 4.0

Body:
I'm making a E-commerce application for my learning purpose. I was using textInput for update quantity in cart page And now I'm using react-native-numeric-input for that.

I'm updating the quantity onChange of react-native-numeric-input, It was working when I tested it normally but when I added my code to update quantity in my database it is not working properply...
here I'm attaching the video of app's abnormal behavior:
Visit link to watch video

this is my code of numeric input component:

<NumericInput
    totalHeight={35}
    totalWidth={80}
    validateOnBlur={false}
    initValue={qtyN}
    separatorWidth={0}
    rounded={true}
    textColor='#2e6153'
    borderColor='#0000'
    inputStyle={{
        backgroundColor: "#fff",
        borderWidth: 1,
        borderColor: '#2e6153',
        borderStyle: 'solid',
    }}
    containerStyle={{
        backgroundColor: '#2e6153',
        borderWidth: 1,
        borderColor: '#2e6153',
        borderStyle: 'solid',
    }}
    iconStyle={{
        color: '#fff',
    }}
    leftButtonBackgroundColor='#2e6153'
    rightButtonBackgroundColor='#2e6153'
    minValue={1}
    maxValue={999}
    onChange={(value) => this.qtyNumHandle(value, data.item.id)}
/>

and function I used on onChange:

qtyNumHandle = async (value, id) => {
    console.log("qtyNum handler");
    console.log(value)
    console.log(id)
    try{
        let user_id = await AsyncStorage.getItem(ID);
        console.log(user_id);
        let updateProduct = await fetch(`http://website.com/api/cart/updatecart?productid=${id}&userid=${user_id}&qty=${value}`, {
            "method": "POST",
            "headers": {
                "cache-control": "no-cache",
            },
        });
        let updateProductRes = await updateProduct.json();
        console.log(updateProductRes);
        this.fetchCartProduct();
    }catch(errors){
        console.log(errors);
    }
}

please tell me if I have done something incorrect. And if my code is correct so why this problem is occurring.

Body:
Yeah..!! I got the solution.

The problem was I was not using the value prop.

Here is my new code of NumericInput:

<NumericInput
    value={this.state.cartTotal[data.index].qty}
    // above the state I've used is containing the array data of my cart products
    // and I used [data.index] because this NumericInput is in FlatList.
    // so to get the quantity of perticular I used it array[data.index].qty
    totalHeight={35}
    totalWidth={80}
    validateOnBlur={false}
    initValue={this.state.cartTotal[data.index].qty}
    separatorWidth={0}
    rounded={true}
    textColor='#2e6153'
    borderColor='#0000'
    inputStyle={{
        backgroundColor: "#fff",
        borderWidth: 1,
        borderColor: '#2e6153',
        borderStyle: 'solid',
    }}
    containerStyle={{
        backgroundColor: '#2e6153',
        borderWidth: 1,
        borderColor: '#2e6153',
        borderStyle: 'solid',
    }}
    iconStyle={{
        color: '#fff',
    }}
    leftButtonBackgroundColor='#2e6153'
    rightButtonBackgroundColor='#2e6153'
    minValue={1}
    maxValue={999}
    onChange={(value) => this.qtyNumHandle(value, data.item.id)}
/>

and here is my function I used on onChange (this has no change):

qtyNumHandle = async (value, id) => {
    console.log("qtyNum handler");
    console.log(value)
    console.log(id)
    try{
        let user_id = await AsyncStorage.getItem(ID);
        console.log(user_id);
        let updateProduct = await fetch(`http://website.com/api/cart/updatecart?productid=${id}&userid=${user_id}&qty=${value}`, {
            "method": "POST",
            "headers": {
                "cache-control": "no-cache",
            },
        });
        let updateProductRes = await updateProduct.json();
        console.log(updateProductRes);
        this.fetchCartProduct();
    }catch(errors){
        console.log(errors);
    }
}

Hope this will help someone else.


问:
Convert a double to NSNumber in Swift
How do I convert a double to NSNumber in Swift?

I tried

```<code>let myDouble = 7.12
NSNumber(myDouble)
</code>```

But got the error:

Argument labels '(_:)' do not match any available overloads

答:
Please, please let Xcode help you. Type NSNumber( and read the suggestions

Or ⌃⌘-click on NSNumber to open the header file

Or read the documentation

Title: Convert a double to NSNumber in Swift

Body:
How do I convert a double to NSNumber in Swift?

I tried

let myDouble = 7.12
NSNumber(myDouble)

But got the error:

Argument labels '(_:)' do not match any available overloads


问:
Simple Word Wrap Function Last Line Problem
I have a function that takes a long string and breaks into smaller strings and adds them to an array so that they can be outputted in a nicer looking paragraph. It works fine except for the last line doesn't output. How would I get it to output? Here's the code:</p>

```<code>void WordWrap(string inputString, string formatedAr[], const int SIZE)
{
    unsigned int length;
    unsigned int index;
    unsigned int word;
    unsigned int max = 65;
    string outWord;
    string outLine;

    length = inputString.length();
    outWord = "";
    outLine = "";
    word = 0;

    for(int i = 0; i < SIZE; i++)
    {
        formatedAr[i] = "";
    }

    for(index = 0; index < length; index++)
    {
        if(inputString[index] != ' ')
        {
            outWord += inputString[index];
        }
        else
        {
            if(outLine.length() + outWord.length() > max)
            {
                formatedAr[word] = outLine;
                word++;
                outLine.clear();
            }
            outLine += outWord + " ";
            outWord.clear();
        }
    }
}
</code>```

答:
You only write into formatedAr when adding a character would make the current line too long. You also need to write the remnant into formatedAr when you've finished parsing the input string.

Try putting formatedAr[word] = outLine; after the for loop finishes.

ContentLicense: CC BY-SA 3.0

Body:
I have a function that takes a long string and breaks into smaller strings and adds them to an array so that they can be outputted in a nicer looking paragraph. It works fine except for the last line doesn't output. How would I get it to output? Here's the code:

void WordWrap(string inputString, string formatedAr[], const int SIZE)
{
    unsigned int length;
    unsigned int index;
    unsigned int word;
    unsigned int max = 65;
    string outWord;
    string outLine;

    length = inputString.length();
    outWord = "";
    outLine = "";
    word = 0;

    for(int i = 0; i < SIZE; i++)
    {
        formatedAr[i] = "";
    }

    for(index = 0; index < length; index++)
    {
        if(inputString[index] != ' ')
        {
            outWord += inputString[index];
        }
        else
        {
            if(outLine.length() + outWord.length() > max)
            {
                formatedAr[word] = outLine;
                word++;
                outLine.clear();
            }
            outLine += outWord + " ";
            outWord.clear();
        }
    }
}


问:
Apple Wallet Passes backend Web services
I have been setting up my backend web services for Apple wallet Passes with NFC enabled. Is there any open sources available for for the complete set up which includes push notification, device registration, creating, updating and downloading passes and all services? can anyone help on this?
Thanks in advance.</p>

答:
For updating passes, there is an implementation of the Passkit Web Service included in the Wallet Companion Files from Apple. </p>

<p>I have not used it, but jpasskit is the only open source implementation I have seen. </p>

Body:
For updating passes, there is an implementation of the Passkit Web Service included in the Wallet Companion Files from Apple.

I have not used it, but jpasskit is the only open source implementation I have seen.


问:
Item overlap in recyclerview
I want to overlap first item on second item in recycler view .

this is what I want to achieve:

this is how my recycler view is looking now:

[]

content inside green border is actually a recyclerView  and the first item in parent recycler view and the rating bar layout is the second item in parent recyclerview .
please suggest me how can i overlap first item on to second item
i have tried this

item_rating_layout:

```<code> <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        style="@style/LayoutHeightWrapWidthMatchStyling"
        android:layout_width="match_parent"
        android:gravity="center_horizontal"
        android:orientation="vertical"
        android:padding="@dimen/padding_large">

        <TextView
            android:id="@+id/tvRatingMessage"
            style="@style/TextStyleNormal.XXLarge"
            android:text="@string/rating_exp" />

        <RatingBar
            android:id="@+id/ratingBar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/margin_medium"
            android:numStars="5"
            android:progressBackgroundTint="@color/gray"
            android:stepSize="1.0"
            android:progressTint="@color/primaryColor"
            android:rating="2.5" />

        <TextView
            android:id="@+id/tvWriteFeedBack"
            style="@style/TextStyleNormal.XXXLarge.primary"
            android:padding="@dimen/padding_medium"
            android:text="Write Feedback"
            android:visibility="gone" />

    </LinearLayout>
</code>```

item_recycler_view:

```<code> <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tool="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/margin_24dp"
        android:layout_marginEnd="@dimen/margin_24dp"
        android:background="@color/warranty_card_background">

        <androidx.core.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@drawable/btn_shap_without_solid_green"
                android:gravity="center_horizontal"
                android:orientation="vertical">

                <ImageView
                    android:id="@+id/ivProductImage"
                    android:layout_width="100dp"
                    android:layout_height="100dp"
                    android:layout_marginTop="@dimen/margin_medium"
                    android:scaleType="fitXY"
                    app:srcCompat="@drawable/ic_original_placeholder" />

                <TextView
                    android:id="@+id/tvName"
                    style="@style/TextStyleNormal.XXLarge.black"
                    android:textStyle="bold"
                    tool:text="Steelbird Air" />

                    <TextView
                        android:id="@+id/tvModel"
                        style="@style/TextStyleNormal.XXLarge"
                        tool:text="SBA-2 Horn Matt Black With Red " />

                <TextView
                    android:id="@+id/tvId"
                    style="@style/TextStyleNormal.XXLarge.gray"
                    android:text="@string/product_id" />

                <TextView
                    android:id="@+id/tvViewProductDetails"
                    style="@style/TextStyleNormal.XLarge.primary"
                    android:text="View product Details" />

                <androidx.recyclerview.widget.RecyclerView
                    android:id="@+id/rvWarrantyCard"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="@dimen/margin_medium"
                    android:layout_marginBottom="@dimen/margin_medium">

                </androidx.recyclerview.widget.RecyclerView>
            </LinearLayout>
        </androidx.core.widget.NestedScrollView>
    </LinearLayout>
</code>```

答:
I somehow fix my problem by just adding a bit of same color as rating bar background on bottom of first item.

now here is the final xml look alike:

item_recycler_view:

```<code><?xml version="1.0" encoding="utf-8"?>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tool="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:id="@+id/llOverlapView"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_gravity="bottom"
        android:background="@color/rating_bar"
        android:orientation="vertical"/>

        <androidx.core.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginStart="@dimen/margin_24dp"
            android:layout_marginEnd="@dimen/margin_24dp"
            android:fillViewport="true">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@drawable/btn_shap_without_solid_green"
                android:gravity="center_horizontal"
                android:orientation="vertical">

                <ImageView
                    android:id="@+id/ivProductImage"
                    android:layout_width="100dp"
                    android:layout_height="100dp"
                    android:layout_marginTop="@dimen/margin_medium"
                    android:scaleType="fitXY"
                    app:srcCompat="@drawable/ic_original_placeholder" />

                <TextView
                    android:id="@+id/tvName"
                    style="@style/TextStyleNormal.XXLarge.black"
                    android:textStyle="bold"
                    tool:text="Steelbird Air" />

                <TextView
                    android:id="@+id/tvModel"
                    style="@style/TextStyleNormal.XXLarge"
                    tool:text="SBA-2 Horn Matt Black With Red " />

                <TextView
                    android:id="@+id/tvId"
                    style="@style/TextStyleNormal.XXLarge.gray"
                    android:text="@string/product_id" />

                <TextView
                    android:id="@+id/tvViewProductDetails"
                    style="@style/TextStyleNormal.XLarge.primary"
                    android:text="View product Details" />

                <androidx.recyclerview.widget.RecyclerView
                    android:id="@+id/rvWarrantyCard"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="@dimen/margin_medium"
                    android:layout_marginBottom="@dimen/margin_medium">

                </androidx.recyclerview.widget.RecyclerView>
            </LinearLayout>
        </androidx.core.widget.NestedScrollView>
</FrameLayout>
</code>```

Big thank to @Pawel

Title: Item overlap in recyclerview

Body:
I want to overlap first item on second item in recycler view .

this is what I want to achieve:

this is how my recycler view is looking now:

[]

content inside green border is actually a recyclerView  and the first item in parent recycler view and the rating bar layout is the second item in parent recyclerview .
please suggest me how can i overlap first item on to second item
i have tried this

item_rating_layout:

 <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        style="@style/LayoutHeightWrapWidthMatchStyling"
        android:layout_width="match_parent"
        android:gravity="center_horizontal"
        android:orientation="vertical"
        android:padding="@dimen/padding_large">

        <TextView
            android:id="@+id/tvRatingMessage"
            style="@style/TextStyleNormal.XXLarge"
            android:text="@string/rating_exp" />

        <RatingBar
            android:id="@+id/ratingBar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/margin_medium"
            android:numStars="5"
            android:progressBackgroundTint="@color/gray"
            android:stepSize="1.0"
            android:progressTint="@color/primaryColor"
            android:rating="2.5" />

        <TextView
            android:id="@+id/tvWriteFeedBack"
            style="@style/TextStyleNormal.XXXLarge.primary"
            android:padding="@dimen/padding_medium"
            android:text="Write Feedback"
            android:visibility="gone" />

    </LinearLayout>

item_recycler_view:

 <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tool="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/margin_24dp"
        android:layout_marginEnd="@dimen/margin_24dp"
        android:background="@color/warranty_card_background">

        <androidx.core.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@drawable/btn_shap_without_solid_green"
                android:gravity="center_horizontal"
                android:orientation="vertical">

                <ImageView
                    android:id="@+id/ivProductImage"
                    android:layout_width="100dp"
                    android:layout_height="100dp"
                    android:layout_marginTop="@dimen/margin_medium"
                    android:scaleType="fitXY"
                    app:srcCompat="@drawable/ic_original_placeholder" />

                <TextView
                    android:id="@+id/tvName"
                    style="@style/TextStyleNormal.XXLarge.black"
                    android:textStyle="bold"
                    tool:text="Steelbird Air" />

                    <TextView
                        android:id="@+id/tvModel"
                        style="@style/TextStyleNormal.XXLarge"
                        tool:text="SBA-2 Horn Matt Black With Red " />

                <TextView
                    android:id="@+id/tvId"
                    style="@style/TextStyleNormal.XXLarge.gray"
                    android:text="@string/product_id" />

                <TextView
                    android:id="@+id/tvViewProductDetails"
                    style="@style/TextStyleNormal.XLarge.primary"
                    android:text="View product Details" />

                <androidx.recyclerview.widget.RecyclerView
                    android:id="@+id/rvWarrantyCard"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="@dimen/margin_medium"
                    android:layout_marginBottom="@dimen/margin_medium">

                </androidx.recyclerview.widget.RecyclerView>
            </LinearLayout>
        </androidx.core.widget.NestedScrollView>
    </LinearLayout>

Body:
I somehow fix my problem by just adding a bit of same color as rating bar background on bottom of first item.

now here is the final xml look alike:

item_recycler_view:

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tool="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:id="@+id/llOverlapView"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_gravity="bottom"
        android:background="@color/rating_bar"
        android:orientation="vertical"/>

        <androidx.core.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginStart="@dimen/margin_24dp"
            android:layout_marginEnd="@dimen/margin_24dp"
            android:fillViewport="true">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@drawable/btn_shap_without_solid_green"
                android:gravity="center_horizontal"
                android:orientation="vertical">

                <ImageView
                    android:id="@+id/ivProductImage"
                    android:layout_width="100dp"
                    android:layout_height="100dp"
                    android:layout_marginTop="@dimen/margin_medium"
                    android:scaleType="fitXY"
                    app:srcCompat="@drawable/ic_original_placeholder" />

                <TextView
                    android:id="@+id/tvName"
                    style="@style/TextStyleNormal.XXLarge.black"
                    android:textStyle="bold"
                    tool:text="Steelbird Air" />

                <TextView
                    android:id="@+id/tvModel"
                    style="@style/TextStyleNormal.XXLarge"
                    tool:text="SBA-2 Horn Matt Black With Red " />

                <TextView
                    android:id="@+id/tvId"
                    style="@style/TextStyleNormal.XXLarge.gray"
                    android:text="@string/product_id" />

                <TextView
                    android:id="@+id/tvViewProductDetails"
                    style="@style/TextStyleNormal.XLarge.primary"
                    android:text="View product Details" />

                <androidx.recyclerview.widget.RecyclerView
                    android:id="@+id/rvWarrantyCard"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="@dimen/margin_medium"
                    android:layout_marginBottom="@dimen/margin_medium">

                </androidx.recyclerview.widget.RecyclerView>
            </LinearLayout>
        </androidx.core.widget.NestedScrollView>
</FrameLayout>

Big thank to @Pawel


问:
How to Read DJI H264 FPV Feed as OpenCV Mat Object?
TDLR: All DJI developers would benefit from decoding raw H264 video stream byte arrays to a format compatible with OpenCV.

I've spent a lot of time looking for a solution to reading DJI's FPV feed as an OpenCV Mat object. I am probably overlooking something fundamental, since I am not too familiar with Image Encoding/Decoding.

Future developers who come across it will likely run into a bunch of the same issues I had. It would be great if DJI developers could use opencv directly without needing a 3rd party library.

I'm willing to use ffmpeg or JavaCV if necessary, but that's quite the hurdle for most Android developers as we're going to have to use cpp, ndk, terminal for testing, etc. That seems like overkill. Both options seem quite time consuming. This JavaCV H264 conversion seems unnecessarily complex. I found it from this relevant question.

I believe the issue lies in the fact that we need to decode both the byte array of length 6 (info array) and the byte array with current frame info simultaneously.

Basically, DJI's FPV feed comes in a number of formats.

Raw H264 (MPEG4) in VideoFeeder.VideoDataListener

```<code>    // The callback for receiving the raw H264 video data for camera live view
    mReceivedVideoDataListener = new VideoFeeder.VideoDataListener() {
        @Override
        public void onReceive(byte[] videoBuffer, int size) {
            //Log.d("BytesReceived", Integer.toString(videoStreamFrameNumber));
            if (videoStreamFrameNumber++%30 == 0){
                //convert video buffer to opencv array
                OpenCvAndModelAsync openCvAndModelAsync = new OpenCvAndModelAsync();
                openCvAndModelAsync.execute(videoBuffer);
            }
            if (mCodecManager != null) {
                mCodecManager.sendDataToDecoder(videoBuffer, size);
            }
        }
    };

</code>```

DJI also has it's own Android decoder sample with FFMPEG to convert to YUV format.

```<code>    @Override
    public void onYuvDataReceived(final ByteBuffer yuvFrame, int dataSize, final int width, final int height) {
        //In this demo, we test the YUV data by saving it into JPG files.
        //DJILog.d(TAG, "onYuvDataReceived " + dataSize);
        if (count++ % 30 == 0 && yuvFrame != null) {
            final byte[] bytes = new byte[dataSize];
            yuvFrame.get(bytes);
            AsyncTask.execute(new Runnable() {
                @Override
                public void run() {
                    if (bytes.length >= width * height) {
                        Log.d("MatWidth", "Made it");
                        YuvImage yuvImage = saveYuvDataToJPEG(bytes, width, height);
                        Bitmap rgbYuvConvert = convertYuvImageToRgb(yuvImage, width, height);

                        Mat yuvMat = new Mat(height, width, CvType.CV_8UC1);
                        yuvMat.put(0, 0, bytes);
                        //OpenCv Stuff
                    }
                }
            });
        }
    }
</code>```

Edit: For those who want to see DJI's YUV to JPEG function, here it is from the sample application:

```<code>private YuvImage saveYuvDataToJPEG(byte[] yuvFrame, int width, int height){
        byte[] y = new byte[width * height];
        byte[] u = new byte[width * height / 4];
        byte[] v = new byte[width * height / 4];
        byte[] nu = new byte[width * height / 4]; //
        byte[] nv = new byte[width * height / 4];

        System.arraycopy(yuvFrame, 0, y, 0, y.length);
        Log.d("MatY", y.toString());
        for (int i = 0; i < u.length; i++) {
            v[i] = yuvFrame[y.length + 2 * i];
            u[i] = yuvFrame[y.length + 2 * i + 1];
        }
        int uvWidth = width / 2;
        int uvHeight = height / 2;
        for (int j = 0; j < uvWidth / 2; j++) {
            for (int i = 0; i < uvHeight / 2; i++) {
                byte uSample1 = u[i * uvWidth + j];
                byte uSample2 = u[i * uvWidth + j + uvWidth / 2];
                byte vSample1 = v[(i + uvHeight / 2) * uvWidth + j];
                byte vSample2 = v[(i + uvHeight / 2) * uvWidth + j + uvWidth / 2];
                nu[2 * (i * uvWidth + j)] = uSample1;
                nu[2 * (i * uvWidth + j) + 1] = uSample1;
                nu[2 * (i * uvWidth + j) + uvWidth] = uSample2;
                nu[2 * (i * uvWidth + j) + 1 + uvWidth] = uSample2;
                nv[2 * (i * uvWidth + j)] = vSample1;
                nv[2 * (i * uvWidth + j) + 1] = vSample1;
                nv[2 * (i * uvWidth + j) + uvWidth] = vSample2;
                nv[2 * (i * uvWidth + j) + 1 + uvWidth] = vSample2;
            }
        }
        //nv21test
        byte[] bytes = new byte[yuvFrame.length];
        System.arraycopy(y, 0, bytes, 0, y.length);
        for (int i = 0; i < u.length; i++) {
            bytes[y.length + (i * 2)] = nv[i];
            bytes[y.length + (i * 2) + 1] = nu[i];
        }
        Log.d(TAG,
              "onYuvDataReceived: frame index: "
                  + DJIVideoStreamDecoder.getInstance().frameIndex
                  + ",array length: "
                  + bytes.length);
        YuvImage yuver = screenShot(bytes,Environment.getExternalStorageDirectory() + "/DJI_ScreenShot", width, height);
        return yuver;
    }

    /**
     * Save the buffered data into a JPG image file
     */
    private YuvImage screenShot(byte[] buf, String shotDir, int width, int height) {
        File dir = new File(shotDir);
        if (!dir.exists() || !dir.isDirectory()) {
            dir.mkdirs();
        }
        YuvImage yuvImage = new YuvImage(buf,
                ImageFormat.NV21,
                width,
                height,
                null);

        OutputStream outputFile = null;

        final String path = dir + "/ScreenShot_" + System.currentTimeMillis() + ".jpg";

        try {
            outputFile = new FileOutputStream(new File(path));
        } catch (FileNotFoundException e) {
            Log.e(TAG, "test screenShot: new bitmap output file error: " + e);
            //return;
        }
        if (outputFile != null) {
            yuvImage.compressToJpeg(new Rect(0,
                    0,
                    width,
                    height), 100, outputFile);
        }
        try {
            outputFile.close();
        } catch (IOException e) {
            Log.e(TAG, "test screenShot: compress yuv image error: " + e);
            e.printStackTrace();
        }

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                displayPath(path);
            }
        });
        return yuvImage;
    }

</code>```

DJI also appears to have a "getRgbaData" function, but there is literally not a single example online or by DJI. Go ahead and Google "DJI getRgbaData"... There's only the reference to the api documentation that explains the self explanatory parameters and return values but nothing else. I couldn't figure out where to call this and there doesn't appear to be a callback function as there is with YUV. You can't call it from the h264b byte array directly, but perhaps you can get it from the yuv data.

Option 1 is much more preferable to option 2, since YUV format has quality issues. Option 3 would also likely involve a decoder.

Here's a screenshot that DJI's own YUV conversion produces.

I've looked at a bunch of things about how to improve the YUV, remove green and yellow colors and whatnot, but at this point if DJI can't do it right, I don't want to invest resources there.

Regarding Option 1, I know there's FFMPEG and JavaCV that seem like good options if I have to go the video decoding route.

Moreover, from what I understand, OpenCV can't handle reading and writing video files without FFMPEG, but I'm not trying to read a video file, I am trying to read an H264/MPEG4 byte[] array. The following code seems to get positive results.

```<code>    /* Async OpenCV Code */
    private class OpenCvAndModelAsync extends AsyncTask<byte[], Void, double[]> {
        @Override
        protected double[] doInBackground(byte[]... params) {//Background Code Executing. Don't touch any UI components
            //get fpv feed and convert bytes to mat array
            Mat videoBufMat = new Mat(4, params[0].length, CvType.CV_8UC4);
            videoBufMat.put(0,0, params[0]);
            //if I add this in it says the bytes are empty.
            //Mat videoBufMat = Imgcodecs.imdecode(encodeVideoBuf, Imgcodecs.IMREAD_ANYCOLOR);
            //encodeVideoBuf.release();
            Log.d("MatRgba", videoBufMat.toString());
            for (int i = 0; i< videoBufMat.rows(); i++){
                for (int j=0; j< videoBufMat.cols(); j++){
                    double[] rgb = videoBufMat.get(i, j);
                    Log.i("Matrix", "red: "+rgb[0]+" green: "+rgb[1]+" blue: "+rgb[2]+" alpha: "
                            + rgb[3] + " Length: " + rgb.length + " Rows: "
                            + videoBufMat.rows() + " Columns: " + videoBufMat.cols());
                }
            }
            double[] center = openCVThingy(videoBufMat);
            return center;
        }
        protected void onPostExecute(double[] center) {
            //handle ui or another async task if necessary
        }
    }

</code>```

Rows = 4, Columns > 30k. I get lots of RGB values that seem valid, such as red = 113, green=75, blue=90, alpha=220 as a made up example; however, I get a ton of 0,0,0,0 values. That should be somewhat okay, since Black is 0,0,0 (although I would have thought the alpha would be higher) and I have a black object in my image. I also don't seem to get any white values 255, 255, 255, even though there is also plenty of white area. I'm not logging the entire byte so it could be there, but I have yet to see it.

However, when I try to compute the contours from this image, I almost always get that the moments (center x, y) are exactly in the center of the image. This error has nothing to do with my color filter or contours algorithm, as I wrote a script in python and tested that I implemented it correctly in Android by reading a still image and getting the exact same number of contours, position, etc in both Python and Android.

I noticed it has something to do with the videoBuffer byte size (bonus points if you can explain why every other length is 6)

```<code>2019-05-23 21:14:29.601 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 2425
2019-05-23 21:14:29.802 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 2659
2019-05-23 21:14:30.004 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 6
2019-05-23 21:14:30.263 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 6015
2019-05-23 21:14:30.507 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 6
2019-05-23 21:14:30.766 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 4682
2019-05-23 21:14:31.005 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 6
2019-05-23 21:14:31.234 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 2840
2019-05-23 21:14:31.433 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 4482
2019-05-23 21:14:31.664 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 6
2019-05-23 21:14:31.927 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 4768
2019-05-23 21:14:32.174 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 6
2019-05-23 21:14:32.433 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 4700
2019-05-23 21:14:32.668 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 6
2019-05-23 21:14:32.864 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 4740
2019-05-23 21:14:33.102 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 6
2019-05-23 21:14:33.365 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 4640
</code>```

My questions:

I. Is this the correct format to read an h264 byte as mat?
Assuming the format is RGBA, that means row = 4 and columns = byte[].length, and CvType.CV_8UC4. Do I have height and width correct? Something tells me YUV height and width is off. I was getting some meaningful results, but the contours were exactly in the center, just like with the H264.

II. Does OpenCV handle MP4 in android like this? If not, do we need to use FFMPEG or JavaCV?

III. Does the int size have something to do with it? Why is the int size occassionally 6, and other times 2400 to 6000? I've heard about the difference between this frames information and information about the next frame, but I'm simply not knowledgeable enough to know how to apply that here.

I'm starting to think this is where the issue lies. Since I need to get the 6 byte array for info about next frame, perhaps my modulo 30 is incorrect. So should I pass the 29th or 31st frame as a format byte for each frame? How is that done in opencv or are we doomed to use the complicated ffmpeg? How would I go about joining the neighboring frames/ byte arrays?

IV. Can I fix this using Imcodecs? I was hoping opencv would natively handle whether a frame was color from this frame or info about next frame. I added the below code, but I am getting an empty array:

```<code>Mat videoBufMat = Imgcodecs.imdecode(new MatOfByte(params[0]), Imgcodecs.IMREAD_UNCHANGED);
</code>```

This also is empty:

```<code>Mat encodeVideoBuf = new Mat(4, params[0].length, CvType.CV_8UC4);
encodeVideoBuf.put(0,0, params[0]);
Mat videoBufMat = Imgcodecs.imdecode(encodeVideoBuf, Imgcodecs.IMREAD_UNCHANGED);
</code>```

V. Should I try converting the bytes into Android jpeg and then import it? Why is djis yuv decoder so complicated looking? It makes me cautious from wanting to try ffmpeg or Javacv and just stick to Android decoder or opencv decoder.

VI. At what stage should I resize the frames to speed up calculations?

Edit: DJI support got back to me and confirmed they don't have any samples for doing what I've described. This is a time for we the community to make this available for everyone!

Upon further research, I don't think opencv will be able to handle this as opencv's android sdk has no functionality for video files/url's (apart from a homegrown MJPEG codec).

So is there a way in Android to convert to mjpeg or similar in order to read? In my application, I only need 1 or 2 frames per second, so perhaps I can save the image as jpeg.

But for real time applications we will likely need to write our own decoder. Please help so that we can make this available to everyone! This question seems promising:

答:
First of all H264 and h264 are different. It is also ez to mix with h264 H264 x264 X264. Last time i use, i remember i use h264 option for DJI device. Make sure you choose correct codec

ffmpeg and ffplay will work directly. I remember Opencv can be built on top of those 2. so shouldn`t be difficult to use the FFMEPG/FFSHOW plug in to convert to cv::Mat. Follow the docuemnts

OpenCV can use the FFmpeg library (http://ffmpeg.org/) as backend to
  record, convert and stream audio and video. FFMpeg is a complete,
  cross-reference solution. If you enable FFmpeg while configuring
  OpenCV than CMake will download and install the binaries in
  OPENCV_SOURCE_CODE/3rdparty/ffmpeg/. To use FFMpeg at runtime, you
  must deploy the FFMepg binaries with your application.

https://docs.opencv.org/3.4/d0/da7/videoio_overview.html

Last time, I have to play with DJI PSDK. And they only allow stream at UDP port  udp://192.168.5.293:23003 with H.264
So I wrote a simple ffmpeg interface to stream to the PSDK. But I have to debug it beforehand.  So I use ffplay to show this network stream to proof it is working. This is the script to show the stream. So you have to work on top of this to work as opencv plugin

```<code>ffplay -f h264 -i udp://192.168.1.45:23003
</code>```

Body:
TDLR: All DJI developers would benefit from decoding raw H264 video stream byte arrays to a format compatible with OpenCV.

I've spent a lot of time looking for a solution to reading DJI's FPV feed as an OpenCV Mat object. I am probably overlooking something fundamental, since I am not too familiar with Image Encoding/Decoding.

Future developers who come across it will likely run into a bunch of the same issues I had. It would be great if DJI developers could use opencv directly without needing a 3rd party library.

I'm willing to use ffmpeg or JavaCV if necessary, but that's quite the hurdle for most Android developers as we're going to have to use cpp, ndk, terminal for testing, etc. That seems like overkill. Both options seem quite time consuming. This JavaCV H264 conversion seems unnecessarily complex. I found it from this relevant question.

I believe the issue lies in the fact that we need to decode both the byte array of length 6 (info array) and the byte array with current frame info simultaneously.

Basically, DJI's FPV feed comes in a number of formats.

Raw H264 (MPEG4) in VideoFeeder.VideoDataListener

    // The callback for receiving the raw H264 video data for camera live view
    mReceivedVideoDataListener = new VideoFeeder.VideoDataListener() {
        @Override
        public void onReceive(byte[] videoBuffer, int size) {
            //Log.d("BytesReceived", Integer.toString(videoStreamFrameNumber));
            if (videoStreamFrameNumber++%30 == 0){
                //convert video buffer to opencv array
                OpenCvAndModelAsync openCvAndModelAsync = new OpenCvAndModelAsync();
                openCvAndModelAsync.execute(videoBuffer);
            }
            if (mCodecManager != null) {
                mCodecManager.sendDataToDecoder(videoBuffer, size);
            }
        }
    };

DJI also has it's own Android decoder sample with FFMPEG to convert to YUV format.

    @Override
    public void onYuvDataReceived(final ByteBuffer yuvFrame, int dataSize, final int width, final int height) {
        //In this demo, we test the YUV data by saving it into JPG files.
        //DJILog.d(TAG, "onYuvDataReceived " + dataSize);
        if (count++ % 30 == 0 && yuvFrame != null) {
            final byte[] bytes = new byte[dataSize];
            yuvFrame.get(bytes);
            AsyncTask.execute(new Runnable() {
                @Override
                public void run() {
                    if (bytes.length >= width * height) {
                        Log.d("MatWidth", "Made it");
                        YuvImage yuvImage = saveYuvDataToJPEG(bytes, width, height);
                        Bitmap rgbYuvConvert = convertYuvImageToRgb(yuvImage, width, height);

                        Mat yuvMat = new Mat(height, width, CvType.CV_8UC1);
                        yuvMat.put(0, 0, bytes);
                        //OpenCv Stuff
                    }
                }
            });
        }
    }

Edit: For those who want to see DJI's YUV to JPEG function, here it is from the sample application:

private YuvImage saveYuvDataToJPEG(byte[] yuvFrame, int width, int height){
        byte[] y = new byte[width * height];
        byte[] u = new byte[width * height / 4];
        byte[] v = new byte[width * height / 4];
        byte[] nu = new byte[width * height / 4]; //
        byte[] nv = new byte[width * height / 4];

        System.arraycopy(yuvFrame, 0, y, 0, y.length);
        Log.d("MatY", y.toString());
        for (int i = 0; i < u.length; i++) {
            v[i] = yuvFrame[y.length + 2 * i];
            u[i] = yuvFrame[y.length + 2 * i + 1];
        }
        int uvWidth = width / 2;
        int uvHeight = height / 2;
        for (int j = 0; j < uvWidth / 2; j++) {
            for (int i = 0; i < uvHeight / 2; i++) {
                byte uSample1 = u[i * uvWidth + j];
                byte uSample2 = u[i * uvWidth + j + uvWidth / 2];
                byte vSample1 = v[(i + uvHeight / 2) * uvWidth + j];
                byte vSample2 = v[(i + uvHeight / 2) * uvWidth + j + uvWidth / 2];
                nu[2 * (i * uvWidth + j)] = uSample1;
                nu[2 * (i * uvWidth + j) + 1] = uSample1;
                nu[2 * (i * uvWidth + j) + uvWidth] = uSample2;
                nu[2 * (i * uvWidth + j) + 1 + uvWidth] = uSample2;
                nv[2 * (i * uvWidth + j)] = vSample1;
                nv[2 * (i * uvWidth + j) + 1] = vSample1;
                nv[2 * (i * uvWidth + j) + uvWidth] = vSample2;
                nv[2 * (i * uvWidth + j) + 1 + uvWidth] = vSample2;
            }
        }
        //nv21test
        byte[] bytes = new byte[yuvFrame.length];
        System.arraycopy(y, 0, bytes, 0, y.length);
        for (int i = 0; i < u.length; i++) {
            bytes[y.length + (i * 2)] = nv[i];
            bytes[y.length + (i * 2) + 1] = nu[i];
        }
        Log.d(TAG,
              "onYuvDataReceived: frame index: "
                  + DJIVideoStreamDecoder.getInstance().frameIndex
                  + ",array length: "
                  + bytes.length);
        YuvImage yuver = screenShot(bytes,Environment.getExternalStorageDirectory() + "/DJI_ScreenShot", width, height);
        return yuver;
    }

    /**
     * Save the buffered data into a JPG image file
     */
    private YuvImage screenShot(byte[] buf, String shotDir, int width, int height) {
        File dir = new File(shotDir);
        if (!dir.exists() || !dir.isDirectory()) {
            dir.mkdirs();
        }
        YuvImage yuvImage = new YuvImage(buf,
                ImageFormat.NV21,
                width,
                height,
                null);

        OutputStream outputFile = null;

        final String path = dir + "/ScreenShot_" + System.currentTimeMillis() + ".jpg";

        try {
            outputFile = new FileOutputStream(new File(path));
        } catch (FileNotFoundException e) {
            Log.e(TAG, "test screenShot: new bitmap output file error: " + e);
            //return;
        }
        if (outputFile != null) {
            yuvImage.compressToJpeg(new Rect(0,
                    0,
                    width,
                    height), 100, outputFile);
        }
        try {
            outputFile.close();
        } catch (IOException e) {
            Log.e(TAG, "test screenShot: compress yuv image error: " + e);
            e.printStackTrace();
        }

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                displayPath(path);
            }
        });
        return yuvImage;
    }

DJI also appears to have a "getRgbaData" function, but there is literally not a single example online or by DJI. Go ahead and Google "DJI getRgbaData"... There's only the reference to the api documentation that explains the self explanatory parameters and return values but nothing else. I couldn't figure out where to call this and there doesn't appear to be a callback function as there is with YUV. You can't call it from the h264b byte array directly, but perhaps you can get it from the yuv data.

Option 1 is much more preferable to option 2, since YUV format has quality issues. Option 3 would also likely involve a decoder.

Here's a screenshot that DJI's own YUV conversion produces.

I've looked at a bunch of things about how to improve the YUV, remove green and yellow colors and whatnot, but at this point if DJI can't do it right, I don't want to invest resources there.

Regarding Option 1, I know there's FFMPEG and JavaCV that seem like good options if I have to go the video decoding route.

Moreover, from what I understand, OpenCV can't handle reading and writing video files without FFMPEG, but I'm not trying to read a video file, I am trying to read an H264/MPEG4 byte[] array. The following code seems to get positive results.

    /* Async OpenCV Code */
    private class OpenCvAndModelAsync extends AsyncTask<byte[], Void, double[]> {
        @Override
        protected double[] doInBackground(byte[]... params) {//Background Code Executing. Don't touch any UI components
            //get fpv feed and convert bytes to mat array
            Mat videoBufMat = new Mat(4, params[0].length, CvType.CV_8UC4);
            videoBufMat.put(0,0, params[0]);
            //if I add this in it says the bytes are empty.
            //Mat videoBufMat = Imgcodecs.imdecode(encodeVideoBuf, Imgcodecs.IMREAD_ANYCOLOR);
            //encodeVideoBuf.release();
            Log.d("MatRgba", videoBufMat.toString());
            for (int i = 0; i< videoBufMat.rows(); i++){
                for (int j=0; j< videoBufMat.cols(); j++){
                    double[] rgb = videoBufMat.get(i, j);
                    Log.i("Matrix", "red: "+rgb[0]+" green: "+rgb[1]+" blue: "+rgb[2]+" alpha: "
                            + rgb[3] + " Length: " + rgb.length + " Rows: "
                            + videoBufMat.rows() + " Columns: " + videoBufMat.cols());
                }
            }
            double[] center = openCVThingy(videoBufMat);
            return center;
        }
        protected void onPostExecute(double[] center) {
            //handle ui or another async task if necessary
        }
    }

Rows = 4, Columns > 30k. I get lots of RGB values that seem valid, such as red = 113, green=75, blue=90, alpha=220 as a made up example; however, I get a ton of 0,0,0,0 values. That should be somewhat okay, since Black is 0,0,0 (although I would have thought the alpha would be higher) and I have a black object in my image. I also don't seem to get any white values 255, 255, 255, even though there is also plenty of white area. I'm not logging the entire byte so it could be there, but I have yet to see it.

However, when I try to compute the contours from this image, I almost always get that the moments (center x, y) are exactly in the center of the image. This error has nothing to do with my color filter or contours algorithm, as I wrote a script in python and tested that I implemented it correctly in Android by reading a still image and getting the exact same number of contours, position, etc in both Python and Android.

I noticed it has something to do with the videoBuffer byte size (bonus points if you can explain why every other length is 6)

2019-05-23 21:14:29.601 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 2425
2019-05-23 21:14:29.802 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 2659
2019-05-23 21:14:30.004 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 6
2019-05-23 21:14:30.263 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 6015
2019-05-23 21:14:30.507 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 6
2019-05-23 21:14:30.766 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 4682
2019-05-23 21:14:31.005 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 6
2019-05-23 21:14:31.234 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 2840
2019-05-23 21:14:31.433 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 4482
2019-05-23 21:14:31.664 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 6
2019-05-23 21:14:31.927 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 4768
2019-05-23 21:14:32.174 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 6
2019-05-23 21:14:32.433 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 4700
2019-05-23 21:14:32.668 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 6
2019-05-23 21:14:32.864 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 4740
2019-05-23 21:14:33.102 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 6
2019-05-23 21:14:33.365 21431-22086/com.dji.simulatorDemo D/VideoBufferSize: 4640

My questions:

I. Is this the correct format to read an h264 byte as mat?
Assuming the format is RGBA, that means row = 4 and columns = byte[].length, and CvType.CV_8UC4. Do I have height and width correct? Something tells me YUV height and width is off. I was getting some meaningful results, but the contours were exactly in the center, just like with the H264.

II. Does OpenCV handle MP4 in android like this? If not, do we need to use FFMPEG or JavaCV?

III. Does the int size have something to do with it? Why is the int size occassionally 6, and other times 2400 to 6000? I've heard about the difference between this frames information and information about the next frame, but I'm simply not knowledgeable enough to know how to apply that here.

I'm starting to think this is where the issue lies. Since I need to get the 6 byte array for info about next frame, perhaps my modulo 30 is incorrect. So should I pass the 29th or 31st frame as a format byte for each frame? How is that done in opencv or are we doomed to use the complicated ffmpeg? How would I go about joining the neighboring frames/ byte arrays?

IV. Can I fix this using Imcodecs? I was hoping opencv would natively handle whether a frame was color from this frame or info about next frame. I added the below code, but I am getting an empty array:

Mat videoBufMat = Imgcodecs.imdecode(new MatOfByte(params[0]), Imgcodecs.IMREAD_UNCHANGED);

This also is empty:

Mat encodeVideoBuf = new Mat(4, params[0].length, CvType.CV_8UC4);
encodeVideoBuf.put(0,0, params[0]);
Mat videoBufMat = Imgcodecs.imdecode(encodeVideoBuf, Imgcodecs.IMREAD_UNCHANGED);

V. Should I try converting the bytes into Android jpeg and then import it? Why is djis yuv decoder so complicated looking? It makes me cautious from wanting to try ffmpeg or Javacv and just stick to Android decoder or opencv decoder.

VI. At what stage should I resize the frames to speed up calculations?

Edit: DJI support got back to me and confirmed they don't have any samples for doing what I've described. This is a time for we the community to make this available for everyone!

Upon further research, I don't think opencv will be able to handle this as opencv's android sdk has no functionality for video files/url's (apart from a homegrown MJPEG codec).

So is there a way in Android to convert to mjpeg or similar in order to read? In my application, I only need 1 or 2 frames per second, so perhaps I can save the image as jpeg.

But for real time applications we will likely need to write our own decoder. Please help so that we can make this available to everyone! This question seems promising:

Body:
First of all H264 and h264 are different. It is also ez to mix with h264 H264 x264 X264. Last time i use, i remember i use h264 option for DJI device. Make sure you choose correct codec

ffmpeg and ffplay will work directly. I remember Opencv can be built on top of those 2. so shouldn`t be difficult to use the FFMEPG/FFSHOW plug in to convert to cv::Mat. Follow the docuemnts

OpenCV can use the FFmpeg library (http://ffmpeg.org/) as backend to
  record, convert and stream audio and video. FFMpeg is a complete,
  cross-reference solution. If you enable FFmpeg while configuring
  OpenCV than CMake will download and install the binaries in
  OPENCV_SOURCE_CODE/3rdparty/ffmpeg/. To use FFMpeg at runtime, you
  must deploy the FFMepg binaries with your application.

https://docs.opencv.org/3.4/d0/da7/videoio_overview.html

Last time, I have to play with DJI PSDK. And they only allow stream at UDP port  udp://192.168.5.293:23003 with H.264
So I wrote a simple ffmpeg interface to stream to the PSDK. But I have to debug it beforehand.  So I use ffplay to show this network stream to proof it is working. This is the script to show the stream. So you have to work on top of this to work as opencv plugin

ffplay -f h264 -i udp://192.168.1.45:23003


问:
How to run two commands with sudo?
Is there any way how I can run two Db2 commands from a command line? They will be called from a PHP exec command.

db2 connect to ttt (note that we need to have the connection live for the second command

db2 UPDATE CONTACT SET EMAIL_ADDRESS = 'mytestaccount@gmail.com'

I tried this:

```<code>sudo -su db2inst1 db2 connect to ttt; db2 UPDATE CONTACT SET EMAIL_ADDRESS = 'mytestaccount@gmail.com'
</code>```

The first command finishes correctly, but the second one fails with the following error message:

SQL1024N  A database connection does not exist.  SQLSTATE=08003

Note that I need to run this as php user. The command sudo -u db2inst1 id as php user gives me correct output.

答:
On a slightly-related topic, I wanted to do the same multi-command sudo via SSH but none of the above worked.

For example on Ubuntu,

```<code>$ ssh host.name sudo sh -c "whoami; whoami"
[sudo] password for ubuntu:
root
ubuntu
</code>```

The trick discovered here is to double-quote the command.

```<code>$ ssh host.name sudo sh -c '"whoami; whoami"'
[sudo] password for ubuntu:
root
root
</code>```

Other options that also work:

```<code>ssh host.name sudo sh -c "\"whoami; whoami\""
ssh host.name 'sudo sh -c "whoami; whoami"'
</code>```

In principle, double-quotes are needed because I think the client shell where SSH is run strips the outermost set of quotes. Mix and match the quotes to your needs (eg. variables need to be passed in). However YMMV with the quotes especially if the remote commands are complex. In that case, a tool like Ansible will make a better choice.

Title: How to run two commands with sudo?

Body:
Is there any way how I can run two Db2 commands from a command line? They will be called from a PHP exec command.

db2 connect to ttt (note that we need to have the connection live for the second command

db2 UPDATE CONTACT SET EMAIL_ADDRESS = 'mytestaccount@gmail.com'

I tried this:

sudo -su db2inst1 db2 connect to ttt; db2 UPDATE CONTACT SET EMAIL_ADDRESS = 'mytestaccount@gmail.com'

The first command finishes correctly, but the second one fails with the following error message:

SQL1024N  A database connection does not exist.  SQLSTATE=08003

Note that I need to run this as php user. The command sudo -u db2inst1 id as php user gives me correct output.

Body:
On a slightly-related topic, I wanted to do the same multi-command sudo via SSH but none of the above worked.

For example on Ubuntu,

$ ssh host.name sudo sh -c "whoami; whoami"
[sudo] password for ubuntu:
root
ubuntu

The trick discovered here is to double-quote the command.

$ ssh host.name sudo sh -c '"whoami; whoami"'
[sudo] password for ubuntu:
root
root

Other options that also work:

ssh host.name sudo sh -c "\"whoami; whoami\""
ssh host.name 'sudo sh -c "whoami; whoami"'

In principle, double-quotes are needed because I think the client shell where SSH is run strips the outermost set of quotes. Mix and match the quotes to your needs (eg. variables need to be passed in). However YMMV with the quotes especially if the remote commands are complex. In that case, a tool like Ansible will make a better choice.


答:
Suggestion:

If I understand it correctly, you want to split a sentence into different words, so instead of doing this:

```<code>for(index = 0; index < length; index++)
    {
        if(inputString[index] != ' ')
        {
            outWord += inputString[index];
        }
</code>```

...

why don't you use streams:

```<code>string s(inputString);
istringstream iss(s);
vector<string> words;
copy (istream_iterator(iss),istream_iterator(),back_inserter(words));
</code>```

Title: Simple Word Wrap Function Last Line Problem

Body:
Suggestion:

If I understand it correctly, you want to split a sentence into different words, so instead of doing this:

for(index = 0; index < length; index++)
    {
        if(inputString[index] != ' ')
        {
            outWord += inputString[index];
        }

...

why don't you use streams:

string s(inputString);
istringstream iss(s);
vector<string> words;
copy (istream_iterator(iss),istream_iterator(),back_inserter(words));


问:
How to add QLabels into QTableWidget with different alignment
I have QTableWidget in which chat messages (normal QLabels) should be added.

I have only one column in this table, while the alignment depends on the sender (me=left, him=right)

I know that I can add a widget into QTableWidget using:

```<code>myTable.setCellWidget(row,0,myQLabel)
</code>```

This adds the label into default alignment. Now, I don't know how to make the alignment dynamic for each row.

I saw some answers doing something like this but the items were not widgets, just texts.

How to make the added QWidget goes into different alignment

答:
You have to establish the alignment to the QLabel:

from PyQt5 import QtCore, QtGui, QtWidgets

class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)

        self.m_table = QtWidgets.QTableWidget(0, 1)
        self.m_table.verticalHeader().hide()
        self.m_table.horizontalHeader().setSectionResizeMode(
            QtWidgets.QHeaderView.Stretch
        )
        self.m_lineedit = QtWidgets.QLineEdit()
        self.left_button = QtWidgets.QPushButton(
            "Left", clicked=self.on_left_clicked
        )
        self.right_button = QtWidgets.QPushButton(
            "Right", clicked=self.on_right_clicked
        )

        lay = QtWidgets.QGridLayout(self)
        lay.addWidget(self.m_table, 0, 0, 1, 2)
        lay.addWidget(self.m_lineedit, 1, 0, 1, 2)
        lay.addWidget(self.left_button, 2, 0)
        lay.addWidget(self.right_button, 2, 1)

    @QtCore.pyqtSlot()
    def on_left_clicked(self):
        self.add_label(self.m_lineedit.text(), QtCore.Qt.AlignLeft)
        self.m_lineedit.clear()
        self.m_table.scrollToBottom()

    @QtCore.pyqtSlot()
    def on_right_clicked(self):
        self.add_label(self.m_lineedit.text(), QtCore.Qt.AlignRight)
        self.m_lineedit.clear()
        self.m_table.scrollToBottom()

    def add_label(self, text, alignment):
        label = QtWidgets.QLabel(text, alignment=alignment)
        row = self.m_table.rowCount()
        self.m_table.insertRow(row)
        self.m_table.setCellWidget(row, 0, label)

if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())
```

<p><img src="https://i.stack.imgur.com/HlyVD.png" alt="enter image description here"></p>

<p><strong>Update:</strong></p>

<p>Another solution is to create a QWidget where the QLabel is placed establishing an alignment to the QLabel with respect to the QWidget.</p>

<pre class="lang-py prettyprint-override"><code>def add_label(self, text, alignment):
    widget = QtWidgets.QWidget()
    widget.setContentsMargins(0, 0, 0, 0)
    lay = QtWidgets.QHBoxLayout(widget)
    lay.setContentsMargins(4, 0, 4, 0)
    label = QtWidgets.QLabel(text)
    lay.addWidget(label, alignment=alignment)
    row = self.m_table.rowCount()
    self.m_table.insertRow(row)
    self.m_table.setCellWidget(row, 0, widget)
</code>```

Body:
I have QTableWidget in which chat messages (normal QLabels) should be added.

I have only one column in this table, while the alignment depends on the sender (me=left, him=right)

I know that I can add a widget into QTableWidget using:

myTable.setCellWidget(row,0,myQLabel)

This adds the label into default alignment. Now, I don't know how to make the alignment dynamic for each row.

I saw some answers doing something like this but the items were not widgets, just texts.

How to make the added QWidget goes into different alignment

Body:
You have to establish the alignment to the QLabel:

from PyQt5 import QtCore, QtGui, QtWidgets

class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)

        self.m_table = QtWidgets.QTableWidget(0, 1)
        self.m_table.verticalHeader().hide()
        self.m_table.horizontalHeader().setSectionResizeMode(
            QtWidgets.QHeaderView.Stretch
        )
        self.m_lineedit = QtWidgets.QLineEdit()
        self.left_button = QtWidgets.QPushButton(
            "Left", clicked=self.on_left_clicked
        )
        self.right_button = QtWidgets.QPushButton(
            "Right", clicked=self.on_right_clicked
        )

        lay = QtWidgets.QGridLayout(self)
        lay.addWidget(self.m_table, 0, 0, 1, 2)
        lay.addWidget(self.m_lineedit, 1, 0, 1, 2)
        lay.addWidget(self.left_button, 2, 0)
        lay.addWidget(self.right_button, 2, 1)

    @QtCore.pyqtSlot()
    def on_left_clicked(self):
        self.add_label(self.m_lineedit.text(), QtCore.Qt.AlignLeft)
        self.m_lineedit.clear()
        self.m_table.scrollToBottom()

    @QtCore.pyqtSlot()
    def on_right_clicked(self):
        self.add_label(self.m_lineedit.text(), QtCore.Qt.AlignRight)
        self.m_lineedit.clear()
        self.m_table.scrollToBottom()

    def add_label(self, text, alignment):
        label = QtWidgets.QLabel(text, alignment=alignment)
        row = self.m_table.rowCount()
        self.m_table.insertRow(row)
        self.m_table.setCellWidget(row, 0, label)

if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

Update:

Another solution is to create a QWidget where the QLabel is placed establishing an alignment to the QLabel with respect to the QWidget.

def add_label(self, text, alignment):
    widget = QtWidgets.QWidget()
    widget.setContentsMargins(0, 0, 0, 0)
    lay = QtWidgets.QHBoxLayout(widget)
    lay.setContentsMargins(4, 0, 4, 0)
    label = QtWidgets.QLabel(text)
    lay.addWidget(label, alignment=alignment)
    row = self.m_table.rowCount()
    self.m_table.insertRow(row)
    self.m_table.setCellWidget(row, 0, widget)


问:
How to import or use functions defined in third party namespace in javascript?
This could be the very basic question of javascript but i am not able to figure out to use the namespance named AudioBridge from the kandy.js file but i dont how should i import the audioBridge namesame in my own js and use it.

Here is the CDN link of kandy.js

Following is the screenshot of the kandy apis AudioBridge feature , how shall i able to use these apis defined in the kandy.js

Link to kandy documentation

答:
In your html you will have you script tag like this:

```

<p>The <code>type</code> is required and will allow you to use imports in your <code>script</code>.</p>

<p>Your Javascript file will then look like this:</p>

```    import { create } from '/whereEverIStore/kandy.js';

    const client = create({
      authentication: { ... },
      logs: { ... },
      // .... more
    });
```

I hope this helps.

NOTE: the { create } syntax is destructuring and can be found here: MDN Destructuring

Body:
In your html you will have you script tag like this:

    <script src="myJavascriptFile.js" type="module"></script>

The type is required and will allow you to use imports in your script.

Your Javascript file will then look like this:

    import { create } from '/whereEverIStore/kandy.js';

    const client = create({
      authentication: { ... },
      logs: { ... },
      // .... more
    });

I hope this helps.

NOTE: the { create } syntax is destructuring and can be found here: MDN Destructuring


问:
How to pass option tags to a custom element as distributed nodes (aka <slot></slot>)
I have a web component custom element defined like so.

```<code> <template id="dropdown-template">
        <select>
            <slot></slot>
        </select>
    </template>
    <script>
        class Dropdown extends HTMLElement {
            constructor() {
                super();
                const shadowRoot = this.attachShadow({mode: 'open'});
                let template = document.getElementById('dropdown-template');
                shadowRoot.appendChild(template.content.cloneNode(true));
            }
        }
        customElements.define("drop-down", Dropdown);
    </script>
</code>```

When trying to use it, I try and pass option tags with values into the custom element.

```<code><drop-down>
     <option>one</option>
     <option>two</option>
     <option>three</option>
</drop-down>
</code>```

This doesn't work. The select element is shown to have a <slot> element as its direct child, and it doesn't render the options. Is this not possible to do with the <select> tag?

答:
It not possible to do it like that because the parent element of an <option> tag must be a <select> tag. So you can use  with Shadow DOM because the <slot> element will break the parent/child hierachy.

Solution 1 : move elements

A workaround is to move the content of the light DOM inside the <select> element in the template.

class Dropdown extends HTMLElement {
    constructor() {
        super()
        const shadowRoot = this.attachShadow( {mode: 'open'} )
        let template = document.getElementById( 'dropdown-template' )
        shadowRoot.appendChild( template.content.cloneNode(true) )

        const select = shadowRoot.querySelector( 'select' )
        shadowRoot.addEventListener( 'slotchange', ev => {
            let node = this.querySelector( 'option' )
            node && select.append( node )
        } )
    }
}
customElements.define("drop-down", Dropdown);```
<pre class="snippet-code-html lang-html prettyprint-override"><code><template id="dropdown-template">
    <select></select>
    <slot></slot>
</template>

<drop-down>
    <option>one</option>
    <option>two</option>
    <option>three</option>
</drop-down></code>```

Solution 2: customized <select>

Another possibility is to avoid Shadow DOM and define your drop-down list as a customized built-in <select> element. Maybe this won't fit your needs if you want to customize the layout.

```<code><select is="drop-down">
    <option>one</option>
    <option>two</option>
    <option>tree</option>
</select>
</code>```

Body:
I have a web component custom element defined like so.

 <template id="dropdown-template">
        <select>
            <slot></slot>
        </select>
    </template>

When trying to use it, I try and pass option tags with values into the custom element.

<drop-down>
     <option>one</option>
     <option>two</option>
     <option>three</option>
</drop-down>

This doesn't work. The select element is shown to have a <slot> element as its direct child, and it doesn't render the options. Is this not possible to do with the <select> tag?

Body:
It not possible to do it like that because the parent element of an <option> tag must be a <select> tag. So you can use  with Shadow DOM because the <slot> element will break the parent/child hierachy.

Solution 1 : move elements

A workaround is to move the content of the light DOM inside the <select> element in the template.

class Dropdown extends HTMLElement {
    constructor() {
        super()
        const shadowRoot = this.attachShadow( {mode: 'open'} )
        let template = document.getElementById( 'dropdown-template' )
        shadowRoot.appendChild( template.content.cloneNode(true) )

        const select = shadowRoot.querySelector( 'select' )
        shadowRoot.addEventListener( 'slotchange', ev => {
            let node = this.querySelector( 'option' )
            node && select.append( node )
        } )
    }
}
customElements.define("drop-down", Dropdown);

<template id="dropdown-template">
    <select></select>
    <slot></slot>
</template>

<drop-down>
    <option>one</option>
    <option>two</option>
    <option>three</option>
</drop-down>

Solution 2: customized <select>

Another possibility is to avoid Shadow DOM and define your drop-down list as a customized built-in <select> element. Maybe this won't fit your needs if you want to customize the layout.

<select is="drop-down">
    <option>one</option>
    <option>two</option>
    <option>tree</option>
</select>


问:
How to introduce lag between various events when using webbrowser contol in winform?
I am developing a c# winform app which controls a website using web browser. I need to perform many events on click of a single button, but many events do not take place until I use a message box to give some sort of lag between events. Below is the code

```<code>private void button5_Click(object sender, EventArgs e)
{
    try
    {
        HtmlDocument webDoc = this.webBrowser1.Document;
        HtmlElementCollection aTags = webDoc.GetElementsByTagName("a");
        string selectedIssue;
        selectedIssue = AcknowledgeList.SelectedItem.ToString();
        foreach (HtmlElement aElement in aTags)
        {
            if (aElement.InnerText.Contains(selectedIssue))
            {
                aElement.InvokeMember("click");

                break;
            }
        }
        MessageBox.Show("Device Acknowledged");

        this.finalAcknowledge();
    }
    catch (NullReferenceException connectionError)
    {
        MessageBox.Show("Connection Error , try again");
    }
}

private void finalAcknowledge()
{
    try
    {
        HtmlDocument webDoc = this.webBrowser1.Document;

        HtmlElement changeNote = webDoc.GetElementById("@note");
        string comment = textBox1.Text;
        changeNote.SetAttribute("value", comment);

        HtmlElementCollection selectTags
            = webDoc.GetElementsByTagName("select");
        foreach (HtmlElement selectElement in selectTags)
        {
            if (selectElement.GetAttribute("name").Equals("status"))
            {
                selectElement.SetAttribute("value", "6");
            }
        }

        HtmlElement submitButton = webDoc.GetElementById("submit_button");
        submitButton.InvokeMember("click");
        this.button3.PerformClick();
        string selectedIssue;
        selectedIssue = AcknowledgeList.SelectedItem.ToString();
        AcknowledgeList.Items.Remove(AcknowledgeList.SelectedItem);
        AssignToList.Items.Add(selectedIssue);

        MessageBox.Show("Device Acknowledged");

        this.callShowAssigned();
    }
    catch (NullReferenceException connectionError)
    {
        MessageBox.Show("Connection Error , try again");
    }
}
</code>```

Here I have used two message boxes to give some lag between events. I want to get rid of these message boxes and want some other method which can perfrom all the events and I do not have to interrupt the user with some message box or something that is visible

答:
Lag can be done with:

```<code>Thread.Sleep(time_to_sleep);
</code>```

But in this case better to use event:
http://msdn.microsoft.com/en-us/library/5d67hf8a.aspx

```<code>webBrowser1.DocumentCompleted+=OnPageLoaded;
</code>```

When you aElement.InvokeMember("click"), you tell to webBrowser1 make some action: post/get to some page. So webbrowser begins job: it makes call to remote server, gets page, renders it. This take time, which can be longer or shorter. This call is made asynchronous, which means, that your code runs forward without waiting for webbrowser to finish. So what can you do? You can subscribe to webbrowser object events, which will hit when browser control finish work.

```<code>//Somewhere before InvokeMember
webBrowser1.DocumentCompleted+=OnPageLoaded;

private void OnPageLoaded(object sender,
        WebBrowserDocumentCompletedEventArgs e)
    {
    //Make your final acknowledgement
    //This method will be executed every time, when your page is loaded
    }
</code>```

Body:
I am developing a c# winform app which controls a website using web browser. I need to perform many events on click of a single button, but many events do not take place until I use a message box to give some sort of lag between events. Below is the code

private void button5_Click(object sender, EventArgs e)
{
    try
    {
        HtmlDocument webDoc = this.webBrowser1.Document;
        HtmlElementCollection aTags = webDoc.GetElementsByTagName("a");
        string selectedIssue;
        selectedIssue = AcknowledgeList.SelectedItem.ToString();
        foreach (HtmlElement aElement in aTags)
        {
            if (aElement.InnerText.Contains(selectedIssue))
            {
                aElement.InvokeMember("click");

                break;
            }
        }
        MessageBox.Show("Device Acknowledged");

        this.finalAcknowledge();
    }
    catch (NullReferenceException connectionError)
    {
        MessageBox.Show("Connection Error , try again");
    }
}

private void finalAcknowledge()
{
    try
    {
        HtmlDocument webDoc = this.webBrowser1.Document;

        HtmlElement changeNote = webDoc.GetElementById("@note");
        string comment = textBox1.Text;
        changeNote.SetAttribute("value", comment);

        HtmlElementCollection selectTags
            = webDoc.GetElementsByTagName("select");
        foreach (HtmlElement selectElement in selectTags)
        {
            if (selectElement.GetAttribute("name").Equals("status"))
            {
                selectElement.SetAttribute("value", "6");
            }
        }

        HtmlElement submitButton = webDoc.GetElementById("submit_button");
        submitButton.InvokeMember("click");
        this.button3.PerformClick();
        string selectedIssue;
        selectedIssue = AcknowledgeList.SelectedItem.ToString();
        AcknowledgeList.Items.Remove(AcknowledgeList.SelectedItem);
        AssignToList.Items.Add(selectedIssue);

        MessageBox.Show("Device Acknowledged");

        this.callShowAssigned();
    }
    catch (NullReferenceException connectionError)
    {
        MessageBox.Show("Connection Error , try again");
    }
}

Here I have used two message boxes to give some lag between events. I want to get rid of these message boxes and want some other method which can perfrom all the events and I do not have to interrupt the user with some message box or something that is visible

Body:
Lag can be done with:

Thread.Sleep(time_to_sleep);

But in this case better to use event:
http://msdn.microsoft.com/en-us/library/5d67hf8a.aspx

webBrowser1.DocumentCompleted+=OnPageLoaded;

When you aElement.InvokeMember("click"), you tell to webBrowser1 make some action: post/get to some page. So webbrowser begins job: it makes call to remote server, gets page, renders it. This take time, which can be longer or shorter. This call is made asynchronous, which means, that your code runs forward without waiting for webbrowser to finish. So what can you do? You can subscribe to webbrowser object events, which will hit when browser control finish work.

//Somewhere before InvokeMember
webBrowser1.DocumentCompleted+=OnPageLoaded;

private void OnPageLoaded(object sender,
        WebBrowserDocumentCompletedEventArgs e)
    {
    //Make your final acknowledgement
    //This method will be executed every time, when your page is loaded
    }


问:
Wpf RichTextBox change key to line break;
I can use Enter key to start a new line but can I use Ctrl+Enter instead?

I want to use Enter key to do other thing.

The KeyDown event I tried not work.

it is always start a new line when I press Enter.

答:
i feel like for this requirement you should use only enter key it will work according to me </p>

```<code> private void richTextBox1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            if (e.KeyCode==Keys.Enter  )
            {
                  //Enter key is down
                //Capture the text in next line  if you press enter only this event will
            }
            }
</code>```

Body:
i feel like for this requirement you should use only enter key it will work according to me

 private void richTextBox1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            if (e.KeyCode==Keys.Enter  )
            {
                  //Enter key is down
                //Capture the text in next line  if you press enter only this event will
            }
            }


问:
Confusing about Kotlin Coroutines execution: where to call await()?
I read a lot of docs about Kotlin coroutines but still having some doubts. I'm using Retrofit with coroutines so I need to do request with Dispatchers.IO context but use result within Dispatchers.Main context to assign it to ViewModel. My code is:</p>

```<code>fun doHttpreq() {
    viewModelScope.launch(Dispatchers.IO) {
        try {
            //should I call await() here? (I guess the correct way to keep execution of request outside of Main thread)
            val request = RestClient.instance.getItems().await()

            withContext(Dispatchers.Main) {
                //or should I call await() here? (BUT need request to be executed outside of Main thread!)

                if (request.isSuccessful) {
                   //asign items to ViewModel

                } else {
                    //asign error to ViewModel
                }
            }

        } catch (e: Exception) {
            withContext(Dispatchers.Main) {
                //asign error to ViewModel
            }
        }
    }
}
</code>```

答:
As Coroutines are suspending instead of blocking, there should not be any need to manage the thread they are running on. In your case Retrofit handles this for you. Also the Deferred type is actually a hot data source. This means that the Call is executed before you even call await on it. await just waits for the data to be there.

So instead you can launch on the Main dispatcher directly. Therefore you only have one place to call await() from.

```<code>viewModelScope.launch(Dispatchers.Main) {
    try {
        val request = RestClient.instance.getItems().await()

        if (request.isSuccessful) {
            //asign items to ViewModel
        } else {
            //asign error to ViewModel
        }
    } catch (e: Exception) {
        //asign error to ViewModel
    }
}
</code>```

Body:
I read a lot of docs about Kotlin coroutines but still having some doubts. I'm using Retrofit with coroutines so I need to do request with Dispatchers.IO context but use result within Dispatchers.Main context to assign it to ViewModel. My code is:

fun doHttpreq() {
    viewModelScope.launch(Dispatchers.IO) {
        try {
            //should I call await() here? (I guess the correct way to keep execution of request outside of Main thread)
            val request = RestClient.instance.getItems().await()

            withContext(Dispatchers.Main) {
                //or should I call await() here? (BUT need request to be executed outside of Main thread!)

                if (request.isSuccessful) {
                   //asign items to ViewModel

                } else {
                    //asign error to ViewModel
                }
            }

        } catch (e: Exception) {
            withContext(Dispatchers.Main) {
                //asign error to ViewModel
            }
        }
    }
}

Body:
As Coroutines are suspending instead of blocking, there should not be any need to manage the thread they are running on. In your case Retrofit handles this for you. Also the Deferred type is actually a hot data source. This means that the Call is executed before you even call await on it. await just waits for the data to be there.

So instead you can launch on the Main dispatcher directly. Therefore you only have one place to call await() from.

viewModelScope.launch(Dispatchers.Main) {
    try {
        val request = RestClient.instance.getItems().await()

        if (request.isSuccessful) {
            //asign items to ViewModel
        } else {
            //asign error to ViewModel
        }
    } catch (e: Exception) {
        //asign error to ViewModel
    }
}


问:
Implementing Matsort and Matpaginator in Angular Material TreeTable Component
I am using a npm library ng-material-treetable. I want to implement matsort and mat paginator in this library.

I was trying to add @ViewChild method in the ng-material-treetable.js file in fesm5 folder of this library but getting error as unexpected identifier @.

Below is the piece of code that was trying to modify (My Line is the piece of code that I have added)-

```<code>Line 394 to 416
    TreetableComponent.prototype.ngOnInit = /**
         * @return {?}
         */
        @ViewChild(MatSort) sort: MatSort;                 //My line
        @ViewChild(MatPaginator) paginator: MatPaginator;  //My line
        function () {
            var _this = this;
            this.tree = Array.isArray(this.tree) ? this.tree : [this.tree];
            this.options = this.parseOptions(defaultOptions);
            /** @type {?} */
            var customOrderValidator = this.validatorService.validateCustomOrder(this.tree[0], this.options.customColumnOrder);
            if (this.options.customColumnOrder && !customOrderValidator.valid) {
                throw new Error("\n        Properties " + customOrderValidator.xor.map(function (x) { return "'" + x + "'"; }).join(', ') + " incorrect or missing in customColumnOrder");
            }
            this.displayedColumns = this.options.customColumnOrder
                ? this.options.customColumnOrder
                : this.extractNodeProps(this.tree[0]);
            this.searchableTree = this.tree.map(function (t) { return _this.converterService.toSearchableTree(t); });
            /** @type {?} */
            var treeTableTree = this.searchableTree.map(function (st) { return _this.converterService.toTreeTableTree(st); });
            this.treeTable = flatMap(treeTableTree, this.treeService.flatten);
            this.dataSource = this.generateDataSource();
            this.dataSource.paginator = this.paginator;  //My line
            this.dataSource.sort = this.sort;            //My line
        };
</code>```

Line 497 to 504 -

```<code>TreetableComponent.decorators = [
        { type: Component, args: [{
                    selector: 'ng-treetable, treetable',
                    // 'ng-treetable' is currently being deprecated
                    template: "<table mat-table [dataSource]=\"dataSource\" matSort [ngClass]=\"formatElevation()\">\n\n  <div *ngFor=\"let column of displayedColumns; first as isFirst;\">\n    <ng-container matColumnDef=\"{{column}}\">\n      <th mat-header-cell *matHeaderCellDef mat-sort-header [ngClass]=\"{'vertical-separator': options.verticalSeparator}\">\n        {{options.capitalisedHeader ? (column | titlecase) : column}}\n      </th>\n      <td mat-cell *matCellDef=\"let element\" [ngClass]=\"{'vertical-separator': options.verticalSeparator}\">\n        <div *ngIf=\"isFirst\">\n          <div class=\"value-cell\">\n            <div [innerHTML]=\"formatIndentation(element)\"></div>\n            <mat-icon [ngStyle]=\"{'visibility': element.children.length ? 'visible' : 'hidden'}\" (click)=\"onNodeClick(element)\">\n              {{element.isExpanded ? 'keyboard_arrow_down' : 'keyboard_arrow_right'}}\n            </mat-icon>\n            <div>{{element.value[column]}}</div>\n          </div>\n        </div>\n        <div *ngIf=\"!isFirst\">\n          {{element.value[column]}}\n        </div>\n      </td>\n    </ng-container>\n  </div>\n\n  <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n  <tr mat-row [ngClass]=\"{'highlight-on-hover': options.highlightRowOnHover}\" *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n\n</table>\n",
                    styles: ["table{width:100%}.value-cell{display:flex;align-items:center}mat-icon{cursor:pointer}.highlight-on-hover:hover{background-color:#f0f0f5}td[class*=' mat-column']{width:10vw;min-width:10vw;max-width:10vw}.mat-cell,.mat-header-cell{padding:10px}.vertical-separator{border-left:1px solid #f0f0f5}"]
                }] }
    ];
</code>```

Here in this template code I have added matSort with table. But this is not working out.Please help if anybody having idea about it.

Note - This piece of code is from that library under folder structure - ng-material-treetable/fesm5/ng-material-treetable.js
Thanks in Advance !!

答:
This is terrible practice.

When using a NPM library, you're not supposed to edit the code of the said library, and I'll explain why :

When you run npm i, you actually install packages from a remote server. THanks to NPM, you don't replace the already existing files if the version hasn't been modified.

So it means that you must have a fixed version in your package.json file. Any semver modificator will erase your modification the second you run npm i.

But the main issue isn't there : the main issue is with the continuous integration, or the teamwork.

When you push your code to github, you don't push your node modules. This means that you don't push your modifications ! And when you have CI, that's your tool that is dowloading the packages, not you : it will download pristine packages, without your modifications.

In the end, the only place where your modification works, is on your own computer.

Finally, even if those issues weren't existing, the packages are written in Javascript. Angular is using Typescript : it then compiles the Typescript into a Javascript bundle.

This means that you can not use Angular code in a JS file. This means no decorators, no dependency injection. If you want to do that, you will have to find the compiled code for the decorators and the compiled code for the dependency injection.

Body:
I am using a npm library ng-material-treetable. I want to implement matsort and mat paginator in this library.

I was trying to add @ViewChild method in the ng-material-treetable.js file in fesm5 folder of this library but getting error as unexpected identifier @.

Below is the piece of code that was trying to modify (My Line is the piece of code that I have added)-

Line 394 to 416
    TreetableComponent.prototype.ngOnInit = /**
         * @return {?}
         */
        @ViewChild(MatSort) sort: MatSort;                 //My line
        @ViewChild(MatPaginator) paginator: MatPaginator;  //My line
        function () {
            var _this = this;
            this.tree = Array.isArray(this.tree) ? this.tree : [this.tree];
            this.options = this.parseOptions(defaultOptions);
            /** @type {?} */
            var customOrderValidator = this.validatorService.validateCustomOrder(this.tree[0], this.options.customColumnOrder);
            if (this.options.customColumnOrder && !customOrderValidator.valid) {
                throw new Error("\n        Properties " + customOrderValidator.xor.map(function (x) { return "'" + x + "'"; }).join(', ') + " incorrect or missing in customColumnOrder");
            }
            this.displayedColumns = this.options.customColumnOrder
                ? this.options.customColumnOrder
                : this.extractNodeProps(this.tree[0]);
            this.searchableTree = this.tree.map(function (t) { return _this.converterService.toSearchableTree(t); });
            /** @type {?} */
            var treeTableTree = this.searchableTree.map(function (st) { return _this.converterService.toTreeTableTree(st); });
            this.treeTable = flatMap(treeTableTree, this.treeService.flatten);
            this.dataSource = this.generateDataSource();
            this.dataSource.paginator = this.paginator;  //My line
            this.dataSource.sort = this.sort;            //My line
        };

Line 497 to 504 -

TreetableComponent.decorators = [
        { type: Component, args: [{
                    selector: 'ng-treetable, treetable',
                    // 'ng-treetable' is currently being deprecated
                    template: "
\n\n
\n    <ng-container matColumnDef=\"{{column}}\">\n      \n        {{options.capitalisedHeader ? (column | titlecase) : column}}\n      	\n      \n
\n
\n

\n            <mat-icon [ngStyle]=\"{'visibility': element.children.length ? 'visible' : 'hidden'}\" (click)=\"onNodeClick(element)\">\n              {{element.isExpanded ? 'keyboard_arrow_down' : 'keyboard_arrow_right'}}\n            </mat-icon>\n
{{element.value[column]}}
\n
\n
\n
\n          {{element.value[column]}}\n
\n      	\n    </ng-container>\n
\n\n

\n

\n\n
\n",
                    styles: ["table{width:100%}.value-cell{display:flex;align-items:center}mat-icon{cursor:pointer}.highlight-on-hover:hover{background-color:#f0f0f5}td[class*=' mat-column']{width:10vw;min-width:10vw;max-width:10vw}.mat-cell,.mat-header-cell{padding:10px}.vertical-separator{border-left:1px solid #f0f0f5}"]
                }] }
    ];

Here in this template code I have added matSort with table. But this is not working out.Please help if anybody having idea about it.

Note - This piece of code is from that library under folder structure - ng-material-treetable/fesm5/ng-material-treetable.js
Thanks in Advance !!