问:
Sending syncronously with System.Net.WebSockets.SendAsync
I'm all in favour of multithreading and asyncronous tasks, but letting go of control isn't my cup of tea.

I'm working on a project where one process is communicating with multiple targets over websockets, and sending should obviously be as speedy as possible, but has to be synced with each other.
Think in line of streaming a videostream to multiple devices simontaniously.
Thus, I don't want to continue sending the next frame before the first one has been receieved by the target.

When using .net WebSockets, I've tried this both with HttpListner and the Kestrel implementation (which I guess is more or less the same), then the socket.SendAsync seems to be receiving the data and buffering it locally before sending it, returning TaskCompleted before its actually sent. This means that the send task basically completes instantly.

I "could" of course implement an ACK schema where the recipient sends an ACK when the whole packet has been received, but that would in itself slow down the process, which I would like to avoid as this is already known by the system itself, as it does try to send the queued up packages continously.

This is basically the code responsible for sending the data, in chunks of 2048b:

```<code>Log.Info($"Send {sendBytes.Length}b");
if (socket!.State == WebSocketState.Open)
{
    await socket.SendAsync(
        sendBuffer,
        WebSocketMessageType.Binary,
        endOfMessage: true,
        cancellationToken: cts
        );
}
Log.Info($"Done ");
</code>```

I would assume the await here would actually wait for the transmission to complete, which is doesn't do, but it seems to await the task completedness.

And on the recipient side this is processing the data, with the debug responses before and after:

```<code>wsClientSession.send("REC " + (String)payloadLength + "b");
ProcessFrame(payload, payloadLength);
wsClientSession.send("ACK " + (String)payloadLength + "b");
</code>```

The logging on the sender side shows this:

Thread 28 is the sending thread, which completes impossibly fast. It needs to send 6198 bytes and chuncks this up in 4 transmissions. It is obviously all done before the first packet has left the server.

The remaining threads are the async recipients of the debug responses.

(size differences are due to the encryption of the data)

```<code>2022-02-07 16:03:34.8887 threadid:28 # Info # Send 6198b to 5d8263c6-909c-47a1-b4d0-57d74d6a4665
2022-02-07 16:03:34.8887 threadid:28 # Info # Send 2048b
2022-02-07 16:03:34.8887 threadid:28 # Info # Done
2022-02-07 16:03:34.8887 threadid:28 # Info # Send 2048b
2022-02-07 16:03:34.8887 threadid:28 # Info # Done
2022-02-07 16:03:34.8887 threadid:28 # Info # Send 2048b
2022-02-07 16:03:34.8887 threadid:28 # Info # Done
2022-02-07 16:03:34.8887 threadid:28 # Info # Send 128b
2022-02-07 16:03:34.8887 threadid:28 # Info # Done
2022-02-07 16:03:34.8887 threadid:28 # Info # Send done to 5d8263c6-909c-47a1-b4d0-57d74d6a4665
2022-02-07 16:03:35.0024 threadid:7 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - REC 2030b
2022-02-07 16:03:35.0090 threadid:7 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - ACK 2030b
2022-02-07 16:03:35.0090 threadid:17 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - REC 2030b
2022-02-07 16:03:35.0260 threadid:33 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - ACK 2030b
2022-02-07 16:03:35.0260 threadid:33 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - REC 2030b
2022-02-07 16:03:35.0260 threadid:30 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - ACK 2030b
2022-02-07 16:03:35.0373 threadid:17 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - REC 108b
2022-02-07 16:03:35.0373 threadid:4 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - ACK 108b
</code>```

Now, is my understanding of this WebSocket implementation all wrong? Is it not possible to have a callback/event or similar on data sent completedness? Can I achieve this in another way?
Executing this true synchronously would be a solution, but I don't seem to be able to force that.

GAAH!!

答:
I'm working on a project where one process is communicating with multiple targets over websockets, and sending should obviously be as speedy as possible, but has to be synced with each other. Think in line of streaming a videostream to multiple devices simontaniously. Thus, I don't want to continue sending the next frame before the first one has been receieved by the target.

Well... actually... both video and audio transmissions tend to use UDP these days and are deliberately designed to allow dropped packets and frames. Missing a single frame in a 30 (or 60) fps source is barely noticeable, but putting a spinner over the video while re-fetching an old frame is very noticeable.

So, perhaps the first thing to consider is that you might want (or need) to relax your requirements. Networking is not the same as hardwired controls, and any solution like this is distributed by nature and therefore must have either some eventual consistency or some partition intolerance (see: CAP theorem).

the socket.SendAsync seems to be receiving the data and buffering it locally before sending it, returning TaskCompleted before its actually sent. This means that the send task basically completes instantly.

This is not just websockets, or .NET, or even Windows. This is (deliberately) how all TCP/IP APIs work. The "send" is considered complete when it reaches the OS buffers. In the TCP/IP world, you are guaranteed that the data will eventually reach the recipient (possibly after retries), or that your socket will eventually enter an error state.

I "could" of course implement an ACK schema where the recipient sends an ACK when the whole packet has been received, but that would in itself slow down the process, which I would like to avoid as this is already known by the system itself, as it does try to send the queued up packages continously.

Websockets do have a message abstraction and maintains message boundaries for you. But websockets are implemented over TCP/IP, which is a stream abstraction (not message or packet). The network itself uses a packet abstraction, and packets are where the ACK/RST/etc come into play. So, the OS is aware of packet-level ACKs/etc and will remove bytes from the TCP/IP stream buffer. But websockets do not have a message-level ACK, so there's no way to know when a message has been received.

Websockets are built on TCP/IP, so you get the same guarantee: you know that a sent message will either (eventually) be received, or (eventually) you will be notified of an error. That's pretty much all you get; the only major difference with TCP/IP is that you get a message abstraction instead of a stream abstraction.

So, your options are:

Accept the eventual consistency. Send messages to all devices simultaneously, and accept that some updates may be delayed.

Accept the partition intolerance. Add an ACK response message, and only send the next update after all devices have ACKed. (This doesn't tolerate partitioning because if one device is disconnected, they all break).

If you do go with the ACK-lockstep approach, you might want to consider using UDP/IP instead of a TCP/IP-based protocol, but that is a whole ton of work.

Executing this true synchronously would be a solution, but I don't seem to be able to force that.

Synchronous APIs are not a solution. There's no API that does what you want; all TCP/IP writes everywhere consider the write "complete" when it reaches the OS; this is true regardless of sync/async, language, runtime, or OS.

Body:
I'm all in favour of multithreading and asyncronous tasks, but letting go of control isn't my cup of tea.

I'm working on a project where one process is communicating with multiple targets over websockets, and sending should obviously be as speedy as possible, but has to be synced with each other.
Think in line of streaming a videostream to multiple devices simontaniously.
Thus, I don't want to continue sending the next frame before the first one has been receieved by the target.

When using .net WebSockets, I've tried this both with HttpListner and the Kestrel implementation (which I guess is more or less the same), then the socket.SendAsync seems to be receiving the data and buffering it locally before sending it, returning TaskCompleted before its actually sent. This means that the send task basically completes instantly.

I "could" of course implement an ACK schema where the recipient sends an ACK when the whole packet has been received, but that would in itself slow down the process, which I would like to avoid as this is already known by the system itself, as it does try to send the queued up packages continously.

This is basically the code responsible for sending the data, in chunks of 2048b:

Log.Info($"Send {sendBytes.Length}b");
if (socket!.State == WebSocketState.Open)
{
    await socket.SendAsync(
        sendBuffer,
        WebSocketMessageType.Binary,
        endOfMessage: true,
        cancellationToken: cts
        );
}
Log.Info($"Done ");

I would assume the await here would actually wait for the transmission to complete, which is doesn't do, but it seems to await the task completedness.

And on the recipient side this is processing the data, with the debug responses before and after:

wsClientSession.send("REC " + (String)payloadLength + "b");
ProcessFrame(payload, payloadLength);
wsClientSession.send("ACK " + (String)payloadLength + "b");

The logging on the sender side shows this:

Thread 28 is the sending thread, which completes impossibly fast. It needs to send 6198 bytes and chuncks this up in 4 transmissions. It is obviously all done before the first packet has left the server.

The remaining threads are the async recipients of the debug responses.

(size differences are due to the encryption of the data)

2022-02-07 16:03:34.8887 threadid:28 # Info # Send 6198b to 5d8263c6-909c-47a1-b4d0-57d74d6a4665
2022-02-07 16:03:34.8887 threadid:28 # Info # Send 2048b
2022-02-07 16:03:34.8887 threadid:28 # Info # Done
2022-02-07 16:03:34.8887 threadid:28 # Info # Send 2048b
2022-02-07 16:03:34.8887 threadid:28 # Info # Done
2022-02-07 16:03:34.8887 threadid:28 # Info # Send 2048b
2022-02-07 16:03:34.8887 threadid:28 # Info # Done
2022-02-07 16:03:34.8887 threadid:28 # Info # Send 128b
2022-02-07 16:03:34.8887 threadid:28 # Info # Done
2022-02-07 16:03:34.8887 threadid:28 # Info # Send done to 5d8263c6-909c-47a1-b4d0-57d74d6a4665
2022-02-07 16:03:35.0024 threadid:7 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - REC 2030b
2022-02-07 16:03:35.0090 threadid:7 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - ACK 2030b
2022-02-07 16:03:35.0090 threadid:17 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - REC 2030b
2022-02-07 16:03:35.0260 threadid:33 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - ACK 2030b
2022-02-07 16:03:35.0260 threadid:33 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - REC 2030b
2022-02-07 16:03:35.0260 threadid:30 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - ACK 2030b
2022-02-07 16:03:35.0373 threadid:17 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - REC 108b
2022-02-07 16:03:35.0373 threadid:4 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - ACK 108b

Now, is my understanding of this WebSocket implementation all wrong? Is it not possible to have a callback/event or similar on data sent completedness? Can I achieve this in another way?
Executing this true synchronously would be a solution, but I don't seem to be able to force that.

GAAH!!


来源: stackexchange

问:
Creating requirements.txt for object-oriented multi-file project with dependencies in python
I created an object-oriented simulation in python that has multiple files with dependencies between them. At the time, I didn't know any better and I didn't create a requirements.txt. I was wondering what the best way is to approach this. I am thinking creating a requirements.txt for each file, and then combining them into one requirements.txt for the whole project (I intend on posting that in my GitHub)

I would love some feedback.

答:
I suggest you to use virtual environments. Create one and install the packages until you successfully run the code. The following materials will help. Automatically create requirements.txt
How to use virtualenv with Python?</p>

ContentLicense: CC BY-SA 4.0


答:
Unless the files are for running independent processes/programs, I think a unified requirements.txt makes sense.

You can do this by running the following command in the terminal:

```<code>pip freeze > requirements.txt
</code>```

Title: Creating requirements.txt for object-oriented multi-file project with dependencies in python

Body:
I created an object-oriented simulation in python that has multiple files with dependencies between them. At the time, I didn't know any better and I didn't create a requirements.txt. I was wondering what the best way is to approach this. I am thinking creating a requirements.txt for each file, and then combining them into one requirements.txt for the whole project (I intend on posting that in my GitHub)

I would love some feedback.

Body:
Unless the files are for running independent processes/programs, I think a unified requirements.txt makes sense.

You can do this by running the following command in the terminal:

pip freeze > requirements.txt


问:
What could cause FileStream to read 0 bytes from an apparently locked file?
I have a 'pack files' method, written in J# that takes a bunch of files and writes them all into a stream, along with some enough metadata that they can be reconstructed as individual files by a related 'unpack' method. I've provided a rough version at the end of this question that gives a good indication of what the underlying J# does. I obtained this by running .NET reflector over the J# code to generate the equivalent J# libraries.

Now the code below works perfectly in developement, but intermittently experiences errors in production. The exceptions labelled in the comments below as 'Error 1' and 'Error 2' have both been seen in the wild. In the case where 'ERROR 2' occurs, there are always 0 bytes written. There is no apparent pattern to when these errors occur. The file sizes involved are typically under 100kb.

The files that get passed into the 'pack' method have very recently been created, as in milliseconds ago, wall-clock time. The output stream points at a file which has newly been created with no sharing.

So to summarize, sometimes I get a file length of '0' returned for a file that I know exists... because I just created it. Due to the involvement of J# I cannot obtain the actual exception. (Of course if I was debugging I could break on the first chance exception, but as mentioned this never happens in the development environment). Other times I am unable to read any bytes out of the file, even though it has been successfully opened. There is exception during the copy process, I can only assume that 'Read' returned -1.

What could be going on here? Any ideas? My suspicion is that there is a virus checked running in Prod, but not dev, and that maybe it's involved somehow. But what could a virus checker do when I have a file open and locked (as in the WriteToStream method) that would cause it to stop reading without an error? I have written up a little test app that can lock arbitrary files... but locking the file from another process doesn't seem to stop FileInfo.Length from working, and once the file stream opens, my test app can no longer lock the file, as you would expect.

I'm stumped, I am.

EDIT:

Okay - here is the J# code instead. Have re-tagged the question.

EDIT 2:

I should also mention that the check for 0 length was added later for trouble-shooting purposes. Prior to that, it was always just failing after comparing 'length' to 'written'.
So whenever 'length' does not equal 'written', sometimes 'length' is 0 and sometimes 'written' is 0. I am confident the problem is NOT a bug in my code, but is caused by something external. The purpose of this question is to find out what another process (e.g. a virus checker) could do to those files to cause my code to fail in the way I describe.

```<code>public static void packContentsToStream(Serializable serializable, Stream stream)
{
    try
    {
        OutputStream output = new StreamWrapperOutputStream(stream);

        FileRecordPair[] recordPairs = SerializationUtil.getRecords(serializable);
        FileRecord[] records = new FileRecord[recordPairs.length];
        File[] files = new Files[recordPairs.length];

        for (int i = 0; i < recordPairs.length; i++)
        {
            FileRecordPair pair = recordPairs[i];
            records[i] = pair.getRecord();
            files[i] = pair.getFile();
        }

        SerializationUtil.writeToStream(serializable, output, false); // False keeps stream open
        SerializationUtil.writeToStream(records, output, false);

        for (int i = 0; i < files.length; i++)
        {
            File file = files[i];
            long written = writeToStream(file, output);
            if (written != records[i].getFileLength())
            {
                throw new SystemException("Invalid record. The number of bytes written [" + written + "] did not match the recorded file length [" + records[i].getFileLength() + "]."); // ERROR 2
            }
        }
     }
     catch (Exception e)
     {
        throw new SystemException("Could not write FileRecords", e);
     }
}

public static long writeToStream(HapiFile file, OutputStream stream)
{
    long written = 0;
    if (file.exists())
    {
        FileInputStream fis = null;
        try
        {
            fis = new FileInputStream(file);
            written = copy(fis, stream);
        }
        catch (Exception e)
        {
            throw new SystemException("Could not write file to stream", e);
        }
        finally
        {
            if (fis != null)
            {
                try
                {
                    fis.close();
                }
                catch (IOException ioe)
                {
                    // For now - throw an exception to see if this might be causing the packing error
                    throw new SystemException("Error closing file", ioe);
                }
            }
        }
    }

    return written;
}

public static int copy(InputStream is, OutputStream stream) throws IOException
{
    int total = 0;
    int read = 0;
    byte[] buffer = new byte[BUFFER_SIZE];

    while (read > -1)
    {
        read = is.read(buffer);
        if (read > 0)
        {
            stream.write(buffer, 0, read);
            total += read;
        }
    }

    return total;
}

// Relevant part of 'SerializationUtil.getRecords'

private static FileRecord GetFor(File file, String recordName, int index, String pathToInstance)
{
    String fileName = file.getName();
    int length = (int) file.length(); // Safe as long as file is under 2GB

    if (length == 0)
    {
        throw new SystemException("Could not obtain file length for '" + file.getPath() + "'"); // ERROR 1
    }

    if (index > -1 && recordName != null && recordName.length() > 0)
    {
        recordName = recordName + "." + index;
    }

    return new FileRecord(fileName, length, recordName, pathToInstance);
}

// File.length() implementation - obtained using .NET Reflector
public virtual long length()
{
    long length = 0L;
    if (this.__fileInfo != null)
    {
        SecurityManager manager = System.getSecurityManager();
        if (manager != null)
        {
            manager.checkRead(this.__mCanonicalPath);
        }
        try
        {
            this.__fileInfo.Refresh();
            if (!this.exists() || !(this.__fileInfo is FileInfo))
            {
                return 0L;
            }
            length = ((FileInfo) this.__fileInfo).Length;
        }
        catch (FileNotFoundException)
        {
        }
        catch (IOException)
        {
        }
    }
    return length;
}
</code>```

答: Never mind... One of the objects in the C# code that was calling the J# code had a finalizer that deleted the file the J# code relied on. The J# code was fine. The virus checker was not to blame. We just had a saboteur in the ranks. The garbage collector was coming in and collecting an object that still appeared to be in scope.

ContentLicense: CC BY-SA 3.0

Body:
I have a 'pack files' method, written in J# that takes a bunch of files and writes them all into a stream, along with some enough metadata that they can be reconstructed as individual files by a related 'unpack' method. I've provided a rough version at the end of this question that gives a good indication of what the underlying J# does. I obtained this by running .NET reflector over the J# code to generate the equivalent J# libraries.

Now the code below works perfectly in developement, but intermittently experiences errors in production. The exceptions labelled in the comments below as 'Error 1' and 'Error 2' have both been seen in the wild. In the case where 'ERROR 2' occurs, there are always 0 bytes written. There is no apparent pattern to when these errors occur. The file sizes involved are typically under 100kb.

The files that get passed into the 'pack' method have very recently been created, as in milliseconds ago, wall-clock time. The output stream points at a file which has newly been created with no sharing.

So to summarize, sometimes I get a file length of '0' returned for a file that I know exists... because I just created it. Due to the involvement of J# I cannot obtain the actual exception. (Of course if I was debugging I could break on the first chance exception, but as mentioned this never happens in the development environment). Other times I am unable to read any bytes out of the file, even though it has been successfully opened. There is exception during the copy process, I can only assume that 'Read' returned -1.

What could be going on here? Any ideas? My suspicion is that there is a virus checked running in Prod, but not dev, and that maybe it's involved somehow. But what could a virus checker do when I have a file open and locked (as in the WriteToStream method) that would cause it to stop reading without an error? I have written up a little test app that can lock arbitrary files... but locking the file from another process doesn't seem to stop FileInfo.Length from working, and once the file stream opens, my test app can no longer lock the file, as you would expect.

I'm stumped, I am.

EDIT:

Okay - here is the J# code instead. Have re-tagged the question.

EDIT 2:

I should also mention that the check for 0 length was added later for trouble-shooting purposes. Prior to that, it was always just failing after comparing 'length' to 'written'.
So whenever 'length' does not equal 'written', sometimes 'length' is 0 and sometimes 'written' is 0. I am confident the problem is NOT a bug in my code, but is caused by something external. The purpose of this question is to find out what another process (e.g. a virus checker) could do to those files to cause my code to fail in the way I describe.

public static void packContentsToStream(Serializable serializable, Stream stream)
{
    try
    {
        OutputStream output = new StreamWrapperOutputStream(stream);

        FileRecordPair[] recordPairs = SerializationUtil.getRecords(serializable);
        FileRecord[] records = new FileRecord[recordPairs.length];
        File[] files = new Files[recordPairs.length];

        for (int i = 0; i < recordPairs.length; i++)
        {
            FileRecordPair pair = recordPairs[i];
            records[i] = pair.getRecord();
            files[i] = pair.getFile();
        }

        SerializationUtil.writeToStream(serializable, output, false); // False keeps stream open
        SerializationUtil.writeToStream(records, output, false);

        for (int i = 0; i < files.length; i++)
        {
            File file = files[i];
            long written = writeToStream(file, output);
            if (written != records[i].getFileLength())
            {
                throw new SystemException("Invalid record. The number of bytes written [" + written + "] did not match the recorded file length [" + records[i].getFileLength() + "]."); // ERROR 2
            }
        }
     }
     catch (Exception e)
     {
        throw new SystemException("Could not write FileRecords", e);
     }
}

public static long writeToStream(HapiFile file, OutputStream stream)
{
    long written = 0;
    if (file.exists())
    {
        FileInputStream fis = null;
        try
        {
            fis = new FileInputStream(file);
            written = copy(fis, stream);
        }
        catch (Exception e)
        {
            throw new SystemException("Could not write file to stream", e);
        }
        finally
        {
            if (fis != null)
            {
                try
                {
                    fis.close();
                }
                catch (IOException ioe)
                {
                    // For now - throw an exception to see if this might be causing the packing error
                    throw new SystemException("Error closing file", ioe);
                }
            }
        }
    }

    return written;
}

public static int copy(InputStream is, OutputStream stream) throws IOException
{
    int total = 0;
    int read = 0;
    byte[] buffer = new byte[BUFFER_SIZE];

    while (read > -1)
    {
        read = is.read(buffer);
        if (read > 0)
        {
            stream.write(buffer, 0, read);
            total += read;
        }
    }

    return total;
}

// Relevant part of 'SerializationUtil.getRecords'

private static FileRecord GetFor(File file, String recordName, int index, String pathToInstance)
{
    String fileName = file.getName();
    int length = (int) file.length(); // Safe as long as file is under 2GB

    if (length == 0)
    {
        throw new SystemException("Could not obtain file length for '" + file.getPath() + "'"); // ERROR 1
    }

    if (index > -1 && recordName != null && recordName.length() > 0)
    {
        recordName = recordName + "." + index;
    }

    return new FileRecord(fileName, length, recordName, pathToInstance);
}

// File.length() implementation - obtained using .NET Reflector
public virtual long length()
{
    long length = 0L;
    if (this.__fileInfo != null)
    {
        SecurityManager manager = System.getSecurityManager();
        if (manager != null)
        {
            manager.checkRead(this.__mCanonicalPath);
        }
        try
        {
            this.__fileInfo.Refresh();
            if (!this.exists() || !(this.__fileInfo is FileInfo))
            {
                return 0L;
            }
            length = ((FileInfo) this.__fileInfo).Length;
        }
        catch (FileNotFoundException)
        {
        }
        catch (IOException)
        {
        }
    }
    return length;
}


问:
KeyboardAvoidingView not working properly with behaviour position
The problem is simple to understand when I click inside the search bar everything goes up, check the images below to understand my problem

<KeyboardAvoidingView
    behavior='position'>
    // code here
</KeyboardAvoidingView >```

Before

After I click on the search bar, basically, everything goes up

答:
its just android thing. so what you need to do is</p>
```<code><KeyboardAvoidingView
  behavior={(Platform.OS === 'ios') ? "padding" : null} enabled
  style={{ flex: 1,  }}>

  // your content

</KeyboardAvoidingView>
</code>```

Body:
The problem is simple to understand when I click inside the search bar everything goes up, check the images below to understand my problem

<KeyboardAvoidingView
    behavior='position'>
    // code here
</KeyboardAvoidingView >

Before

After I click on the search bar, basically, everything goes up

Body:
its just android thing. so what you need to do is

<KeyboardAvoidingView
  behavior={(Platform.OS === 'ios') ? "padding" : null} enabled
  style={{ flex: 1,  }}>

  // your content

</KeyboardAvoidingView>


问:
Makefile: return first two characters of a string
Given a string in a Makefile, is it possible to extract the first two characters of an unknown string using Makefile syntax (without using shell calls)?

for instance,

```<code>VAR := UnKnown
VAR_TERSE = $(call get_first_two_chars, $(VAR))

define get_first_two_char
...
endef
</code>```

答:
Well, it can be done, but it's pretty messy to implement by hand.  The easiest thing to do is to get the GNU Make Standard Library, which has a built-in substr function.  If that's overkill, you can extract just that function from the library, but like I said, it's surprisingly messy.

Essentially you do a series of substitutions on the string to insert a space after each character:

```<code>EMPTY:=
SPACE:=$(EMPTY) $(EMPTY)
VAR := UnKnown
TMP:=$(subst a,a ,$(subst b,b ,$(subst c,c ,.........$(VAR)))))
# TMP now has "U n K n o w n"
</code>```

Next you can use the $(wordlist) function to grab the first two "words" of the intermediate result:

```<code>TMP2:=$(wordlist 1,2,$(TMP))
# TMP2 now has "U n"
</code>```

Finally, you use $(subst) again, now to strip out the space that you injected originally:

```<code>VAR_TERSE := $(subst $(SPACE),,$(TMP2))
# VAR_TERSE now has "Un"
</code>```

Body:
Given a string in a Makefile, is it possible to extract the first two characters of an unknown string using Makefile syntax (without using shell calls)?

for instance,

VAR := UnKnown
VAR_TERSE = $(call get_first_two_chars, $(VAR))

define get_first_two_char
...
endef

Body:
Well, it can be done, but it's pretty messy to implement by hand.  The easiest thing to do is to get the GNU Make Standard Library, which has a built-in substr function.  If that's overkill, you can extract just that function from the library, but like I said, it's surprisingly messy.

Essentially you do a series of substitutions on the string to insert a space after each character:

EMPTY:=
SPACE:=$(EMPTY) $(EMPTY)
VAR := UnKnown
TMP:=$(subst a,a ,$(subst b,b ,$(subst c,c ,.........$(VAR)))))
# TMP now has "U n K n o w n"

Next you can use the $(wordlist) function to grab the first two "words" of the intermediate result:

TMP2:=$(wordlist 1,2,$(TMP))
# TMP2 now has "U n"

Finally, you use $(subst) again, now to strip out the space that you injected originally:

VAR_TERSE := $(subst $(SPACE),,$(TMP2))
# VAR_TERSE now has "Un"


问:
Failed to connect to shadowsocks client
I've configured shadowsocks system by running ss-server on VPS and ss-local on my client machine.
Then I made a simple SOCKS5 client which connects to ss-local and resolve SOCKS request using C.
All work well, when I run ss-tunnel instead of ss-local, my SOCKS5 client can't connect to ss-tunnel.

TCP connection terminates as soon as it established.
I'm not sure what is the proper reason.

```<code>ss-tunnel -c config.json -L <destaddr:port>
</code>```

But it does when I run ss-local instead.

```<code>ss-local -c config.json
</code>```

Below is my config file.

```<code>{
    "server":"xxx.xxx.xxx.xxx",
    "server_port":443,
    "local_address": "127.0.0.1",
    "local_port":10800,
    "password":"xxxxxxxxxx",
    "timeout":60,
    "method":"chacha20-ietf-poly1305",
    "workers":8,
    "plugin":"obfs-local",
    "plugin_opts":"obfs=tls;obfs-host=www.google.com"
}
</code>```

Is there any difference between protocols of ss-local and ss-tunnel? I know it's false, but anyway can't get it how they go wrong.
Thanks.

答:
ss-tunnel establishes a complete tunnel with ss-server, all traffic to ss-tunnel is directly relayed to ss-server without any SOCKS request/resolve processes.
After I've removed SOCKS handshake in my client program, it worked properly.</p>

Title: Failed to connect to shadowsocks client

Body:
I've configured shadowsocks system by running ss-server on VPS and ss-local on my client machine.
Then I made a simple SOCKS5 client which connects to ss-local and resolve SOCKS request using C.
All work well, when I run ss-tunnel instead of ss-local, my SOCKS5 client can't connect to ss-tunnel.

TCP connection terminates as soon as it established.
I'm not sure what is the proper reason.

ss-tunnel -c config.json -L <destaddr:port>

But it does when I run ss-local instead.

ss-local -c config.json

Below is my config file.

{
    "server":"xxx.xxx.xxx.xxx",
    "server_port":443,
    "local_address": "127.0.0.1",
    "local_port":10800,
    "password":"xxxxxxxxxx",
    "timeout":60,
    "method":"chacha20-ietf-poly1305",
    "workers":8,
    "plugin":"obfs-local",
    "plugin_opts":"obfs=tls;obfs-host=www.google.com"
}

Is there any difference between protocols of ss-local and ss-tunnel? I know it's false, but anyway can't get it how they go wrong.
Thanks.


问:
I already have 'color' and 'fill' legends. How can I control the colour of a line produced using geom_vline?
I'm trying to product a bar plot and line plot on the same axes, with a rectangle to show where data may be incomplete and vertical lines showing important dates.

```<code>library(dplyr)
library(ggplot2)
library(scales)

dates <- c("2022-01-01","2022-01-08","2022-01-15")
count_variables <- c('pass','fail')
counts <- c(30,28,26,10,11,12)

data_bar <- expand.grid(date = dates, count_variable = count_variables, stringsAsFactors = F)
data_bar$count <- counts
data_bar$date <- as.Date(data_bar$date)

ave_marks <- c(75,72,68)

data_line <- data.frame(date = dates,
                        perc = ave_marks,
                        perc_variable = 'average mark')
data_line$date <- as.Date(data_line$date)

ggplot() +
  # Rectangle covering last few days
  geom_rect(aes(xmin=max(data_bar$date)+4, xmax=max(data_bar$date), ymin=-Inf, ymax=Inf,
                fill="Time period subject\nto reporting delays"), colour=NA, alpha = .2) +
  # Bar plot
  geom_bar(data=data_bar, aes(fill=count_variable, y=count, x=date), position="dodge", stat="identity") +
  scale_fill_manual(labels = c("Pass","Fail","Time period subject\nto reporting delays"),
                    values = c("green","red","#e4004620")) +
  # Line plot
  geom_line(data=data_line, aes(x=date, y=perc/3, color=perc_variable)) +
  #scale_color_manual(labels = c("Pass rate"), values = c("blue")) +
  # Vertical lines
  geom_vline(aes(xintercept = as.Date("2022-01-05"),linetype = "Exam change 1 announced"),color='orange') +
  geom_vline(aes(xintercept = as.Date("2022-01-06"),linetype = "Exam change 1"),color='orange') +
  geom_vline(aes(xintercept = as.Date("2022-01-12"),linetype = "Exam change 2 announced"),color='black') +
  geom_vline(aes(xintercept = as.Date("2022-01-13"),linetype = "Exam change 2"),color='black') +
  scale_color_manual(labels = c("Pass rate","Exam change 1 announced","Exam change 1",
                                "Exam change 2 announced","Exam change 2"),
                     values = c("blue","orange","orange","black","black")) +
  scale_linetype_manual(values=c("longdash","solid","longdash","solid"),
                        limits=c("Exam change 1 announced","Exam change 1",
                                 "Exam change 2 announced","Exam change 2"),
                        labels = c("Exam change 1 announced","Exam change 1",
                                   "Exam change 2 announced","Exam change 2")) +
  scale_y_continuous(sec.axis = sec_axis(~.*3, name = 'Percentage'),
                     labels = comma)
</code>```

The code produces this chart.

The chart looks how I want it to, apart from the legend, which does not show the difference in colour between the lines that represent the two exam changes. How can I make the legend show 'Exam change 1 announced' and 'Exam change 1' in orange, rather than black?

答:
One option to achieve your desired result would be to override the aesthetics applied to your linetype legend using the override.aes argument of guide_legend which allows you to set the colors for each legend item:

library(dplyr)
library(ggplot2)
library(scales)

ggplot() +
  # Rectangle covering last few days
  geom_rect(aes(
    xmin = max(data_bar$date) + 4, xmax = max(data_bar$date), ymin = -Inf, ymax = Inf,
    fill = "Time period subject\nto reporting delays"
  ), colour = NA, alpha = .2) +
  # Bar plot
  geom_bar(data = data_bar, aes(fill = count_variable, y = count, x = date), position = "dodge", stat = "identity") +
  scale_fill_manual(
    labels = c("Pass", "Fail", "Time period subject\nto reporting delays"),
    values = c("green", "red", "#e4004620")
  ) +
  # Line plot
  geom_line(data = data_line, aes(x = date, y = perc / 3, color = perc_variable)) +
  # scale_color_manual(labels = c("Pass rate"), values = c("blue")) +
  # Vertical lines
  geom_vline(aes(xintercept = as.Date("2022-01-05"), linetype = "Exam change 1 announced"), color = "orange") +
  geom_vline(aes(xintercept = as.Date("2022-01-06"), linetype = "Exam change 1"), color = "orange") +
  geom_vline(aes(xintercept = as.Date("2022-01-12"), linetype = "Exam change 2 announced"), color = "black") +
  geom_vline(aes(xintercept = as.Date("2022-01-13"), linetype = "Exam change 2"), color = "black") +
  scale_color_manual(
    labels = c(
      "Pass rate", "Exam change 1 announced", "Exam change 1",
      "Exam change 2 announced", "Exam change 2"
    ),
    values = c("blue", "orange", "orange", "black", "black")
  ) +
  scale_linetype_manual(
    values = c("longdash", "solid", "longdash", "solid"),
    limits = c(
      "Exam change 1 announced", "Exam change 1",
      "Exam change 2 announced", "Exam change 2"
    ),
    labels = c(
      "Exam change 1 announced", "Exam change 1",
      "Exam change 2 announced", "Exam change 2"
    )
  ) +
  scale_y_continuous(
    sec.axis = sec_axis(~ . * 3, name = "Percentage"),
    labels = comma
  ) +
  guides(linetype = guide_legend(override.aes = list(color = c("orange", "orange", "black", "black"))))
```

Body:
I'm trying to product a bar plot and line plot on the same axes, with a rectangle to show where data may be incomplete and vertical lines showing important dates.

library(dplyr)
library(ggplot2)
library(scales)

dates <- c("2022-01-01","2022-01-08","2022-01-15")
count_variables <- c('pass','fail')
counts <- c(30,28,26,10,11,12)

data_bar <- expand.grid(date = dates, count_variable = count_variables, stringsAsFactors = F)
data_bar$count <- counts
data_bar$date <- as.Date(data_bar$date)

ave_marks <- c(75,72,68)

data_line <- data.frame(date = dates,
                        perc = ave_marks,
                        perc_variable = 'average mark')
data_line$date <- as.Date(data_line$date)

ggplot() +
  # Rectangle covering last few days
  geom_rect(aes(xmin=max(data_bar$date)+4, xmax=max(data_bar$date), ymin=-Inf, ymax=Inf,
                fill="Time period subject\nto reporting delays"), colour=NA, alpha = .2) +
  # Bar plot
  geom_bar(data=data_bar, aes(fill=count_variable, y=count, x=date), position="dodge", stat="identity") +
  scale_fill_manual(labels = c("Pass","Fail","Time period subject\nto reporting delays"),
                    values = c("green","red","#e4004620")) +
  # Line plot
  geom_line(data=data_line, aes(x=date, y=perc/3, color=perc_variable)) +
  #scale_color_manual(labels = c("Pass rate"), values = c("blue")) +
  # Vertical lines
  geom_vline(aes(xintercept = as.Date("2022-01-05"),linetype = "Exam change 1 announced"),color='orange') +
  geom_vline(aes(xintercept = as.Date("2022-01-06"),linetype = "Exam change 1"),color='orange') +
  geom_vline(aes(xintercept = as.Date("2022-01-12"),linetype = "Exam change 2 announced"),color='black') +
  geom_vline(aes(xintercept = as.Date("2022-01-13"),linetype = "Exam change 2"),color='black') +
  scale_color_manual(labels = c("Pass rate","Exam change 1 announced","Exam change 1",
                                "Exam change 2 announced","Exam change 2"),
                     values = c("blue","orange","orange","black","black")) +
  scale_linetype_manual(values=c("longdash","solid","longdash","solid"),
                        limits=c("Exam change 1 announced","Exam change 1",
                                 "Exam change 2 announced","Exam change 2"),
                        labels = c("Exam change 1 announced","Exam change 1",
                                   "Exam change 2 announced","Exam change 2")) +
  scale_y_continuous(sec.axis = sec_axis(~.*3, name = 'Percentage'),
                     labels = comma)

The code produces this chart.

The chart looks how I want it to, apart from the legend, which does not show the difference in colour between the lines that represent the two exam changes. How can I make the legend show 'Exam change 1 announced' and 'Exam change 1' in orange, rather than black?


问:
How to subtract columns of one dataframe to that of another in python and store the result and both columns in a new dataframe
I’ve 2 data frames which have one common column ‘X’ having all the unique values. I want to subtract each column of data frame 1 to that of data frame 2 which have similar names.
dataframe 1

X
bar A
bar B

A1
48.0
1235

A2
53.0
4567

dataframe 2

X
par A
par B

A2
74.0
8342

A1
63.0
6531

Desired result:

X
bar A
par A
Difference
Status

A1
48.0
63.0
15.0
Ok

A2
53.0
74.0
21.0
Ok

To be noted that Difference here refers to barA - parA I.e subtraction.
and this kind of data frames are required for each column
There are 20 columns in my data frames. The status column gets not ok when value is less Than 0.

I’m thinking of writing a for loop to perform this but unable to start. If anyone can help in this. Ps I’m working on python.

答:
Your expected output and logic is a bit ambiguous, I'll assume here that you want to subtract the column of df2 that has the same trailing letter as the column in df1. Then compute the status if all differences are positive:

```<code>df3 = df1.merge(df2, on='X').set_index('X')

(df3.groupby(df3.columns.map(lambda x: x.split()[1]), axis=1)
    .apply(lambda d: d.diff(axis=1).iloc[:,-1])
    .add_prefix('diff_')
    .assign(Status=lambda d: np.where(d.ge(0).all(1), 'OK', 'Not OK'))
)
</code>```

output:

```<code>     diff_A  diff_B Status
X
A1     15.0  5296.0     OK
A2     21.0  3775.0     OK
</code>```

Body:
Your expected output and logic is a bit ambiguous, I'll assume here that you want to subtract the column of df2 that has the same trailing letter as the column in df1. Then compute the status if all differences are positive:

df3 = df1.merge(df2, on='X').set_index('X')

(df3.groupby(df3.columns.map(lambda x: x.split()[1]), axis=1)
    .apply(lambda d: d.diff(axis=1).iloc[:,-1])
    .add_prefix('diff_')
    .assign(Status=lambda d: np.where(d.ge(0).all(1), 'OK', 'Not OK'))
)

output:

     diff_A  diff_B Status
X
A1     15.0  5296.0     OK
A2     21.0  3775.0     OK


问:
validation of input from user using python
I have written the below code to know the mood of the user. the code runs successfully except for the data input validation function. In my case if the user enters the value above 3 the code accept it and enters the value as none in the array. whereas i need the code to validate and tell that the input entered is wrong and please enter the correct value.

please help me with input validation.

The code is below

```<code>def let_user_pick(options):
    print("Please choose:")
    for idx, element in enumerate(options):
        print("{}) {}".format(idx+1,element))
    i = input("Enter number: ")
    try:
        if 0 < int(i) <= len(options):
            return int(i)
    except:
        pass
    return None

def _sum(arr):
    sum=0
    for i in arr: sum = sum + i
    return(sum)

color=["Red","orange","green"]
Animal=["Dog","lizard","Donkey"]
Food=["Ice-cream","Vegetables","Exotic-food"]
Book=["the kite runner","Winter Garden","White Trash"]
Smell=["Floral","Chemical","Sweet"]
a=[]

print("Input the color from the list")
a.append(let_user_pick(color))

print("Input the Animal from the list")
a.append(let_user_pick(Animal))

print("Input the Food from the list")
a.append(let_user_pick(Food))

print("Input the Book from the list")
a.append(let_user_pick(Book))

print("Input the Smell from the list")
a.append(let_user_pick(Smell))

print(a)
ans = _sum(a)
print(ans)

if (ans == 15 and ans >= 13) :
    print("User is anxious")
elif (ans == 12 and ans >= 10):
    print("user is Happy")
elif (ans == 9 and ans >= 6) :
    print("user is Neutral ")
elif (ans == 5 and ans >=4) :
    print("user is Sad")
else:
    print("user is angry")
</code>```

答:
The problem is that you don't check the output of the function whether it is None or a number you can do this:

```<code>user_choice = let_user_pick(<array>)
if user_choice is None:
    print("Please Enter a Number below 3")
    let_user_pick(<array>)
else:
    a.append(user_choice)

</code>```

You can develop your code by making it a while loop until all the answers are correct then break the loop and continue what you were doing.

Edit: it looks like my code didn't seem to work with you, so I edited it with a tested code, here it is:

```<code>print("Input the color from the list")
while True:
    user_input = let_user_pick(color)
    if user_input is None:
        print("Please choose a number below 4")
        data = let_user_pick(color)
    else:
        a.append(user_input)
        break
</code>```

and yeah absolutely you can apply this to the others, or you can combine them all and make it one while loop

Body:
I have written the below code to know the mood of the user. the code runs successfully except for the data input validation function. In my case if the user enters the value above 3 the code accept it and enters the value as none in the array. whereas i need the code to validate and tell that the input entered is wrong and please enter the correct value.

please help me with input validation.

The code is below

def let_user_pick(options):
    print("Please choose:")
    for idx, element in enumerate(options):
        print("{}) {}".format(idx+1,element))
    i = input("Enter number: ")
    try:
        if 0 < int(i) <= len(options):
            return int(i)
    except:
        pass
    return None

def _sum(arr):
    sum=0
    for i in arr: sum = sum + i
    return(sum)

color=["Red","orange","green"]
Animal=["Dog","lizard","Donkey"]
Food=["Ice-cream","Vegetables","Exotic-food"]
Book=["the kite runner","Winter Garden","White Trash"]
Smell=["Floral","Chemical","Sweet"]
a=[]

print("Input the color from the list")
a.append(let_user_pick(color))

print("Input the Animal from the list")
a.append(let_user_pick(Animal))

print("Input the Food from the list")
a.append(let_user_pick(Food))

print("Input the Book from the list")
a.append(let_user_pick(Book))

print("Input the Smell from the list")
a.append(let_user_pick(Smell))

print(a)
ans = _sum(a)
print(ans)

if (ans == 15 and ans >= 13) :
    print("User is anxious")
elif (ans == 12 and ans >= 10):
    print("user is Happy")
elif (ans == 9 and ans >= 6) :
    print("user is Neutral ")
elif (ans == 5 and ans >=4) :
    print("user is Sad")
else:
    print("user is angry")

Body:
The problem is that you don't check the output of the function whether it is None or a number you can do this:

user_choice = let_user_pick(<array>)
if user_choice is None:
    print("Please Enter a Number below 3")
    let_user_pick(<array>)
else:
    a.append(user_choice)

You can develop your code by making it a while loop until all the answers are correct then break the loop and continue what you were doing.

Edit: it looks like my code didn't seem to work with you, so I edited it with a tested code, here it is:

print("Input the color from the list")
while True:
    user_input = let_user_pick(color)
    if user_input is None:
        print("Please choose a number below 4")
        data = let_user_pick(color)
    else:
        a.append(user_input)
        break

and yeah absolutely you can apply this to the others, or you can combine them all and make it one while loop


问:
Visual Studio interactive window unreadable highlighted error
Recently, Visual Studio started highlighting errors in the interactive window, which makes them unreadable:

How can I remove or change the highlight color? I looked around SO but can't find any of the settings mentioned (e.g. this).

I am using the standard VS dark theme. Other dark themes didn't solve the issue

答:
Following rioV8's instructions, I added the following to my settings.json:

```<code>"workbench.colorCustomizations": {
    "terminal.ansiYellow": "#1e1e1e"
}
</code>```

Replaces the awful yellow with the same background color as the interactive window in the default dark mode. Works for VSCode v1.63.2.

Body:
Following rioV8's instructions, I added the following to my settings.json:

"workbench.colorCustomizations": {
    "terminal.ansiYellow": "#1e1e1e"
}

Replaces the awful yellow with the same background color as the interactive window in the default dark mode. Works for VSCode v1.63.2.


问:
How can I expand a short URL, so I can get the full expanded URL in a variable?
I want to expand a short URL and store the long URL in a variable without accessing that link with the browser. Any ideas how I can do that in kotlin?</p>

答:
If your nodejs backend redirects the short url to a long url, you can create an API endpoint to fetch the long URL from your backend.

General idea is to send an HTTP HEAD request to the server which in turn will return a 301 response (Moved Permanently) with the Location header which contains the URI

HEAD /5b2su2 HTTP/1.1
Host: tinyurl.com
Accept: /

RESPONSE:

```<code>HTTP/1.1 301 Moved Permanently
Location: http://stackoverflow.com
Content-type: text/html
Date: Sat, 23 May 2009 18:58:24 GMT
Server: TinyURL/1.6
</code>```

This is much faster than opening the actual URL and you don't really want to fetch the redirected URL. It also plays nice with the tinyurl service.

Look into any HTTP or curl APIs available.

If you are using a third-party service to convert long URLs to short URLs, that same service provider must have an API endpoint which converts your short URL to long URL.

Body:
If your nodejs backend redirects the short url to a long url, you can create an API endpoint to fetch the long URL from your backend.

General idea is to send an HTTP HEAD request to the server which in turn will return a 301 response (Moved Permanently) with the Location header which contains the URI

HEAD /5b2su2 HTTP/1.1
Host: tinyurl.com
Accept: /

RESPONSE:

HTTP/1.1 301 Moved Permanently
Location: http://stackoverflow.com
Content-type: text/html
Date: Sat, 23 May 2009 18:58:24 GMT
Server: TinyURL/1.6

This is much faster than opening the actual URL and you don't really want to fetch the redirected URL. It also plays nice with the tinyurl service.

Look into any HTTP or curl APIs available.

If you are using a third-party service to convert long URLs to short URLs, that same service provider must have an API endpoint which converts your short URL to long URL.


问:
Android 12 APK throws invalid package upon install
I have an Azure build pipeline which is producing an APK which installs (via AppCenter) just fine on Android 10 but pops up the error:

App not installed as package appears to be invalid

on Android 12.

The AndroidManifest.xml in the solution looks like this:

```<code><?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.app.myapplocal" android:installLocation="auto" android:versionCode="1" android:versionName="1.1">
    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" />
    <uses-permission android:name="android.permission.FLASHLIGHT" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAMERA" />
    <application android:label="L MyApp" android:icon="@drawable/icon" android:largeHeap="true"></application>
</manifest>
</code>```

When I examine the manifest via Android Studio's APK Analyze option, I see this:

```<code><uses-sdk
    android:minSdkVersion="21"
    android:targetSdkVersion="31" />

<uses-permission
    android:name="android.permission.FLASHLIGHT" />

<uses-permission
    android:name="android.permission.INTERNET" />

<uses-permission
    android:name="android.permission.CAMERA" />

<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<application
    android:label="D MyApp"
    android:icon="@ref/0x7f07015e"
    android:name="crc646948444ac10504e5.MainApplication"
    android:debuggable="true"
    android:allowBackup="true"
    android:largeHeap="true"
    android:extractNativeLibs="true">

    <meta-data
        android:name="com.google.android.gms.vision.DEPENDENCIES"
        android:value="barcode" />

    <activity
        android:theme="@ref/0x7f0d0001"
        android:label="MyApp"
        android:icon="@ref/0x7f07015e"
        android:name="crc646948444ac10504e5.MainActivity"
        android:screenOrientation="1"
        android:configChanges="0x680" />

    <activity
        android:theme="@ref/0x7f0d0000"
        android:name="crc646948444ac10504e5.SplashActivity"
        android:exported="true"
        android:screenOrientation="1"
        android:noHistory="true">

        <intent-filter>

            <action
                android:name="android.intent.action.MAIN" />

            <category
                android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <activity
        android:label="Web Authenticator"
        android:name="crc641e66d166111bdf3e.FormAuthenticatorActivity" />

    <activity
        android:label="Web Authenticator"
        android:name="crc641e66d166111bdf3e.WebAuthenticatorActivity" />

    <activity
        android:label="Web Authenticator Native Browser"
        android:name="crc641e66d166111bdf3e.WebAuthenticatorNativeBrowserActivity"
        android:launchMode="1" />

    <activity
        android:name="com.microsoft.windowsazure.mobileservices.authentication.RedirectUrlActivity" />

    <service
        android:name="crc64a98abb514ffad9f1.KeepAliveService" />

    <receiver
        android:label="Essentials Connectivity Broadcast Receiver"
        android:name="crc64a0e0a82d0db9a07d.ConnectivityBroadcastReceiver"
        android:enabled="true"
        android:exported="false" />

    <receiver
        android:name="crc643f46942d9dd1fff9.PowerSaveModeBroadcastReceiver"
        android:enabled="true"
        android:exported="false" />

    <provider
        android:name="mono.android.MultiDexLoader"
        android:exported="false"
        android:authorities="com.app.myapp.mono.android.MultiDexLoader.__mono_init__"
        android:initOrder="1999999999" />

    <provider
        android:name="mono.MonoRuntimeProvider"
        android:exported="false"
        android:authorities="com.app.myapp.mono.MonoRuntimeProvider.__mono_init__"
        android:initOrder="1999999998" />

    <activity
        android:theme="@ref/0x01030010"
        android:name="com.google.android.gms.common.api.GoogleApiActivity"
        android:exported="false" />

    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@ref/0x7f090008" />
</application>

<uses-permission
    android:name="android.permission.ACCESS_NETWORK_STATE" />
</code>```

I had previously thought that the problem with Android 12 was that the android:targetSdkVersion was set to 29 but changing this in the solution's manifest and changing the project file's TargetFrameworkVersion from v11.0 to v12.0 did not help either. (This was updated in Visual Studio using the project properties' Application > Compile using Android version value.)

What might I be missing in order to allow installing on recent Android devices? (I am not familiar with Xamarin or Android, I'm afraid.)

答:
If you have bumped the compile version to 31, then you need to add

```<code>android:exported="true"
</code>```

To your activities, services and receivers. See here.

In your case

```<code><uses-sdk
    android:minSdkVersion="21"
    android:targetSdkVersion="31" />

<uses-permission
    android:name="android.permission.FLASHLIGHT" />

<uses-permission
    android:name="android.permission.INTERNET" />

<uses-permission
    android:name="android.permission.CAMERA" />

<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<application
    android:label="D MyApp"
    android:icon="@ref/0x7f07015e"
    android:name="crc646948444ac10504e5.MainApplication"
    android:debuggable="true"
    android:allowBackup="true"
    android:largeHeap="true"
    android:extractNativeLibs="true">

    <meta-data
        android:name="com.google.android.gms.vision.DEPENDENCIES"
        android:value="barcode" />

    <activity
        android:theme="@ref/0x7f0d0001"
        android:label="MyApp"
        android:icon="@ref/0x7f07015e"
        android:name="crc646948444ac10504e5.MainActivity"
        android:screenOrientation="1"
        android:configChanges="0x680"
        android:exported="true"/>

    <activity
        android:theme="@ref/0x7f0d0000"
        android:name="crc646948444ac10504e5.SplashActivity"
        android:exported="true"
        android:screenOrientation="1"
        android:noHistory="true">

        <intent-filter>

            <action
                android:name="android.intent.action.MAIN" />

            <category
                android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <activity
        android:label="Web Authenticator"
        android:name="crc641e66d166111bdf3e.FormAuthenticatorActivity"
        android:exported="true"/>

    <activity
        android:label="Web Authenticator"
        android:name="crc641e66d166111bdf3e.WebAuthenticatorActivity"
        android:exported="true"/>

    <activity
        android:label="Web Authenticator Native Browser"
        android:name="crc641e66d166111bdf3e.WebAuthenticatorNativeBrowserActivity"
        android:launchMode="1"
        android:exported="true"/>

    <activity
        android:name="com.microsoft.windowsazure.mobileservices.authentication.RedirectUrlActivity"
        android:exported="true"/>

    <service
        android:name="crc64a98abb514ffad9f1.KeepAliveService"
        android:exported="true"/>
    <receiver
        android:label="Essentials Connectivity Broadcast Receiver"
        android:name="crc64a0e0a82d0db9a07d.ConnectivityBroadcastReceiver"
        android:enabled="true"
        android:exported="false" />

    <receiver
        android:name="crc643f46942d9dd1fff9.PowerSaveModeBroadcastReceiver"
        android:enabled="true"
        android:exported="false" />

    <provider
        android:name="mono.android.MultiDexLoader"
        android:exported="false"
        android:authorities="com.app.myapp.mono.android.MultiDexLoader.__mono_init__"
        android:initOrder="1999999999" />

    <provider
        android:name="mono.MonoRuntimeProvider"
        android:exported="false"
        android:authorities="com.app.myapp.mono.MonoRuntimeProvider.__mono_init__"
        android:initOrder="1999999998" />

    <activity
        android:theme="@ref/0x01030010"
        android:name="com.google.android.gms.common.api.GoogleApiActivity"
        android:exported="false" />

    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@ref/0x7f090008" />
</application>

<uses-permission
    android:name="android.permission.ACCESS_NETWORK_STATE" />
</code>```

Please be wary of what really needs to be exported or not and change accordingly.

It could also be the case that App Center as of Android 11 requires a mandatory app signer, see here, here, and just in case, here is the snippet

As of Android 11, it's mandatory to use the APK signer (if you use API level 30) as it will set some extra schemes "APK Signature Scheme v2 now required". App Center now (since Dec 17, 2020) signs Android applications using APK signer internally, instead of JAR signer which was used previously. As part of the feature to enable APK signer in App Center, Android signing task V3 was implemented, and requirements for new Signing task were to change how keystore file is saved - to store the keystore file in an AzDO secure file (Android signing build and release task - Azure Pipelines | Microsoft Docs).

Warning
Any build configurations that had their keystore files uploaded prior to Dec 17, 2020 still use the APK Signature Scheme v2 signing method (jarsigner). To use the APK Signature Scheme v3 signing flow, users just have to re-upload their keystore files and save their branch configuration.

Body:
I have an Azure build pipeline which is producing an APK which installs (via AppCenter) just fine on Android 10 but pops up the error:

App not installed as package appears to be invalid

on Android 12.

The AndroidManifest.xml in the solution looks like this:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.app.myapplocal" android:installLocation="auto" android:versionCode="1" android:versionName="1.1">
    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" />
    <uses-permission android:name="android.permission.FLASHLIGHT" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAMERA" />
    <application android:label="L MyApp" android:icon="@drawable/icon" android:largeHeap="true"></application>
</manifest>

When I examine the manifest via Android Studio's APK Analyze option, I see this:

<uses-sdk
    android:minSdkVersion="21"
    android:targetSdkVersion="31" />

<uses-permission
    android:name="android.permission.FLASHLIGHT" />

<uses-permission
    android:name="android.permission.INTERNET" />

<uses-permission
    android:name="android.permission.CAMERA" />

<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<application
    android:label="D MyApp"
    android:icon="@ref/0x7f07015e"
    android:name="crc646948444ac10504e5.MainApplication"
    android:debuggable="true"
    android:allowBackup="true"
    android:largeHeap="true"
    android:extractNativeLibs="true">

    <meta-data
        android:name="com.google.android.gms.vision.DEPENDENCIES"
        android:value="barcode" />

    <activity
        android:theme="@ref/0x7f0d0001"
        android:label="MyApp"
        android:icon="@ref/0x7f07015e"
        android:name="crc646948444ac10504e5.MainActivity"
        android:screenOrientation="1"
        android:configChanges="0x680" />

    <activity
        android:theme="@ref/0x7f0d0000"
        android:name="crc646948444ac10504e5.SplashActivity"
        android:exported="true"
        android:screenOrientation="1"
        android:noHistory="true">

        <intent-filter>

            <action
                android:name="android.intent.action.MAIN" />

            <category
                android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <activity
        android:label="Web Authenticator"
        android:name="crc641e66d166111bdf3e.FormAuthenticatorActivity" />

    <activity
        android:label="Web Authenticator"
        android:name="crc641e66d166111bdf3e.WebAuthenticatorActivity" />

    <activity
        android:label="Web Authenticator Native Browser"
        android:name="crc641e66d166111bdf3e.WebAuthenticatorNativeBrowserActivity"
        android:launchMode="1" />

    <activity
        android:name="com.microsoft.windowsazure.mobileservices.authentication.RedirectUrlActivity" />

    <service
        android:name="crc64a98abb514ffad9f1.KeepAliveService" />

    <receiver
        android:label="Essentials Connectivity Broadcast Receiver"
        android:name="crc64a0e0a82d0db9a07d.ConnectivityBroadcastReceiver"
        android:enabled="true"
        android:exported="false" />

    <receiver
        android:name="crc643f46942d9dd1fff9.PowerSaveModeBroadcastReceiver"
        android:enabled="true"
        android:exported="false" />

    <provider
        android:name="mono.android.MultiDexLoader"
        android:exported="false"
        android:authorities="com.app.myapp.mono.android.MultiDexLoader.__mono_init__"
        android:initOrder="1999999999" />

    <provider
        android:name="mono.MonoRuntimeProvider"
        android:exported="false"
        android:authorities="com.app.myapp.mono.MonoRuntimeProvider.__mono_init__"
        android:initOrder="1999999998" />

    <activity
        android:theme="@ref/0x01030010"
        android:name="com.google.android.gms.common.api.GoogleApiActivity"
        android:exported="false" />

    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@ref/0x7f090008" />
</application>

<uses-permission
    android:name="android.permission.ACCESS_NETWORK_STATE" />

I had previously thought that the problem with Android 12 was that the android:targetSdkVersion was set to 29 but changing this in the solution's manifest and changing the project file's TargetFrameworkVersion from v11.0 to v12.0 did not help either. (This was updated in Visual Studio using the project properties' Application > Compile using Android version value.)

What might I be missing in order to allow installing on recent Android devices? (I am not familiar with Xamarin or Android, I'm afraid.)

Body:
If you have bumped the compile version to 31, then you need to add

android:exported="true"

To your activities, services and receivers. See here.

In your case

<uses-sdk
    android:minSdkVersion="21"
    android:targetSdkVersion="31" />

<uses-permission
    android:name="android.permission.FLASHLIGHT" />

<uses-permission
    android:name="android.permission.INTERNET" />

<uses-permission
    android:name="android.permission.CAMERA" />

<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<application
    android:label="D MyApp"
    android:icon="@ref/0x7f07015e"
    android:name="crc646948444ac10504e5.MainApplication"
    android:debuggable="true"
    android:allowBackup="true"
    android:largeHeap="true"
    android:extractNativeLibs="true">

    <meta-data
        android:name="com.google.android.gms.vision.DEPENDENCIES"
        android:value="barcode" />

    <activity
        android:theme="@ref/0x7f0d0001"
        android:label="MyApp"
        android:icon="@ref/0x7f07015e"
        android:name="crc646948444ac10504e5.MainActivity"
        android:screenOrientation="1"
        android:configChanges="0x680"
        android:exported="true"/>

    <activity
        android:theme="@ref/0x7f0d0000"
        android:name="crc646948444ac10504e5.SplashActivity"
        android:exported="true"
        android:screenOrientation="1"
        android:noHistory="true">

        <intent-filter>

            <action
                android:name="android.intent.action.MAIN" />

            <category
                android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <activity
        android:label="Web Authenticator"
        android:name="crc641e66d166111bdf3e.FormAuthenticatorActivity"
        android:exported="true"/>

    <activity
        android:label="Web Authenticator"
        android:name="crc641e66d166111bdf3e.WebAuthenticatorActivity"
        android:exported="true"/>

    <activity
        android:label="Web Authenticator Native Browser"
        android:name="crc641e66d166111bdf3e.WebAuthenticatorNativeBrowserActivity"
        android:launchMode="1"
        android:exported="true"/>

    <activity
        android:name="com.microsoft.windowsazure.mobileservices.authentication.RedirectUrlActivity"
        android:exported="true"/>

    <service
        android:name="crc64a98abb514ffad9f1.KeepAliveService"
        android:exported="true"/>
    <receiver
        android:label="Essentials Connectivity Broadcast Receiver"
        android:name="crc64a0e0a82d0db9a07d.ConnectivityBroadcastReceiver"
        android:enabled="true"
        android:exported="false" />

    <receiver
        android:name="crc643f46942d9dd1fff9.PowerSaveModeBroadcastReceiver"
        android:enabled="true"
        android:exported="false" />

    <provider
        android:name="mono.android.MultiDexLoader"
        android:exported="false"
        android:authorities="com.app.myapp.mono.android.MultiDexLoader.__mono_init__"
        android:initOrder="1999999999" />

    <provider
        android:name="mono.MonoRuntimeProvider"
        android:exported="false"
        android:authorities="com.app.myapp.mono.MonoRuntimeProvider.__mono_init__"
        android:initOrder="1999999998" />

    <activity
        android:theme="@ref/0x01030010"
        android:name="com.google.android.gms.common.api.GoogleApiActivity"
        android:exported="false" />

    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@ref/0x7f090008" />
</application>

<uses-permission
    android:name="android.permission.ACCESS_NETWORK_STATE" />

Please be wary of what really needs to be exported or not and change accordingly.

It could also be the case that App Center as of Android 11 requires a mandatory app signer, see here, here, and just in case, here is the snippet

As of Android 11, it's mandatory to use the APK signer (if you use API level 30) as it will set some extra schemes "APK Signature Scheme v2 now required". App Center now (since Dec 17, 2020) signs Android applications using APK signer internally, instead of JAR signer which was used previously. As part of the feature to enable APK signer in App Center, Android signing task V3 was implemented, and requirements for new Signing task were to change how keystore file is saved - to store the keystore file in an AzDO secure file (Android signing build and release task - Azure Pipelines | Microsoft Docs).

Warning
Any build configurations that had their keystore files uploaded prior to Dec 17, 2020 still use the APK Signature Scheme v2 signing method (jarsigner). To use the APK Signature Scheme v3 signing flow, users just have to re-upload their keystore files and save their branch configuration.


问:
ReactJs: Prevent multiple times button press
In my React component I have a button meant to send some data over AJAX when clicked. I need to happen only the first time, i.e. to disable the button after its first use.

How I'm trying to do this:

```<code>var UploadArea = React.createClass({

  getInitialState() {
    return {
      showUploadButton: true
    };
  },

  disableUploadButton(callback) {
    this.setState({ showUploadButton: false }, callback);
  },

  // This was simpler before I started trying everything I could think of
  onClickUploadFile() {
    if (!this.state.showUploadButton) {
      return;
    }
    this.disableUploadButton(function() {
      $.ajax({
        [...]
      });

    });
  },

  render() {
    var uploadButton;
    if (this.state.showUploadButton) {
      uploadButton = (
        <button onClick={this.onClickUploadFile}>Send</button>
      );
    }

    return (
      <div>
        {uploadButton}
      </div>
    );
  }

});
</code>```

What I think happens is the state variable showUploadButton not being updated right away, which the React docs says is expected.

How could I enforce the button to get disabled or go away altogether the instant it's being clicked?

答:
Another approach could be like so:</p>
```<code><button onClick={this.handleClick} disabled={isLoading ? "disabled" :""}>Send</button>
</code>```

Body:
In my React component I have a button meant to send some data over AJAX when clicked. I need to happen only the first time, i.e. to disable the button after its first use.

How I'm trying to do this:

var UploadArea = React.createClass({

  getInitialState() {
    return {
      showUploadButton: true
    };
  },

  disableUploadButton(callback) {
    this.setState({ showUploadButton: false }, callback);
  },

  // This was simpler before I started trying everything I could think of
  onClickUploadFile() {
    if (!this.state.showUploadButton) {
      return;
    }
    this.disableUploadButton(function() {
      $.ajax({
        [...]
      });

    });
  },

  render() {
    var uploadButton;
    if (this.state.showUploadButton) {
      uploadButton = (
        <button onClick={this.onClickUploadFile}>Send</button>
      );
    }

    return (

        {uploadButton}

    );
  }

});

What I think happens is the state variable showUploadButton not being updated right away, which the React docs says is expected.

How could I enforce the button to get disabled or go away altogether the instant it's being clicked?

Body:
Another approach could be like so:

<button onClick={this.handleClick} disabled={isLoading ? "disabled" :""}>Send</button>


问:
React doesn't call useEffect on firebase (v9) auth update
I'm uploading a user profile image into firebase storage, then updating the photoURL value of the auth user with updateProfile(). After that I want the user to be updated without manually refreshing the page. I've been trying this for days now and the issue gets more weird every time I try to debug it.

The interesting thing is the user object seems to be already updated when I log it with console.log(currentUser) after the then promise of updateProfile() is fulfilled. So the new photoURL is already present in the currentUser object. But it seems to not call a state update or console.log("!!!!currentAuthUserUpdate", user);. So the user image wouldn't refresh in my page.

I even tried it with doing a useEffect with the currentUser as a dependency but it wasn't fired. Still, the currentUser object changed when logging it after updateProfile()

Updating the profile, UpdateUserImage.tsx:

```<code>import { useAuth } from "../../contexts/AuthContext";

const { currentUser } = useAuth();

// updating the user profile
updateProfile(currentUser, { photoURL })
</code>```

AuthContext.tsx:

```<code>import { auth } from "./../firebase/firebase";

const [currentUser, setCurrentUser] = useState(null);

const auth = getAuth(app);

  useEffect(() => {
    const unsubscribe = auth.onAuthStateChanged((user) => {
      console.log("!!!!currentAuthUserUpdate", user);

      // I tried setting the user as a custom new object: const userData = { ...user };
      setCurrentUser(user);
    });
    return unsubscribe;
  }, []);
</code>```

firebase.js

```<code>import { getAuth } from "firebase/auth";

// Initialize Firebase
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);

export {
  auth
};
</code>```

What I tried additionally: (But this wouldn't work as the user is already updated without a state refresh from react, so it's trying to replace the same object)

```<code>const reloadUser = async () => {
    try {
      const res = await currentUser.reload();
      const user = auth.currentUser;
      console.log("currentUser:", user);

      setCurrentUser(auth.currentUser);

      console.log("res", res);
    } catch (err) {
      console.log(err);
    }
  };
</code>```

答:
The setCurrentUser function returned from useState isn't always the same function in my experience.

You can try passing it as a dependency into the useEffect - but I don't think that's what you want.

React lets you use an old useState setter if you give it an updater function, rather than a value: setCurrentUser(()=>auth.currentUser)

The React docs dispute this though.

Body:
I'm uploading a user profile image into firebase storage, then updating the photoURL value of the auth user with updateProfile(). After that I want the user to be updated without manually refreshing the page. I've been trying this for days now and the issue gets more weird every time I try to debug it.

The interesting thing is the user object seems to be already updated when I log it with console.log(currentUser) after the then promise of updateProfile() is fulfilled. So the new photoURL is already present in the currentUser object. But it seems to not call a state update or console.log("!!!!currentAuthUserUpdate", user);. So the user image wouldn't refresh in my page.

I even tried it with doing a useEffect with the currentUser as a dependency but it wasn't fired. Still, the currentUser object changed when logging it after updateProfile()

Updating the profile, UpdateUserImage.tsx:

import { useAuth } from "../../contexts/AuthContext";

const { currentUser } = useAuth();

// updating the user profile
updateProfile(currentUser, { photoURL })

AuthContext.tsx:

import { auth } from "./../firebase/firebase";

const [currentUser, setCurrentUser] = useState(null);

const auth = getAuth(app);

  useEffect(() => {
    const unsubscribe = auth.onAuthStateChanged((user) => {
      console.log("!!!!currentAuthUserUpdate", user);

      // I tried setting the user as a custom new object: const userData = { ...user };
      setCurrentUser(user);
    });
    return unsubscribe;
  }, []);

firebase.js

import { getAuth } from "firebase/auth";

// Initialize Firebase
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);

export {
  auth
};

What I tried additionally: (But this wouldn't work as the user is already updated without a state refresh from react, so it's trying to replace the same object)

const reloadUser = async () => {
    try {
      const res = await currentUser.reload();
      const user = auth.currentUser;
      console.log("currentUser:", user);

      setCurrentUser(auth.currentUser);

      console.log("res", res);
    } catch (err) {
      console.log(err);
    }
  };


问:
how to vectorize the scatter-matmul operation
I have many matrices w1, w2, w3...wn with shapes (k*n1, k*n2, k*n3...k*nn) and x1, x2, x3...xn with shapes (n1*m, n2*m, n3*m...nn*m).

I want to get w1@x1, w2@x2, w3@x3 ... respectively.

The resulting matrix is multiple k*m matrices and can be concatenated into a large matrix with shape (k*n)*m.

Multiply them one by one will be slow. How to vectorize this operation?

Note: The input can be a k*(n1+n2+n3+...+nn) matrix and a (n1+n2+n3+...+nn)*m matrix, and we may use a batch index to indicate those submatrices.

This operation is related to the scatter operations implemented in pytorch_scatter, so I refer it as "scatter_matmul".

答: Please take a look at this link. Apparently DGL is working on something similar already: https://github.com/dmlc/dgl/pull/3641</p>


问:
FCM intermittenly generates wrong token
I have tried to search the solutions everywhere, like several links below but couldn't find any correct answer.

FCM token Not Generating

What is FCM token in Firebase?

Firebase FCM force onTokenRefresh() to be called

The problem is every time I tried doing fresh install, both from Android Studio and Play Store, FCM sometimes generates a right token, but sometimes it generarates a wrong token. Whilst the right token is always different, the wrong token is always the same, starting with eyJhb. I know this info is useless since FCM generates the token based on device ID and app ID.

I've forced FCM to generate the token using this code in my LoginActivity.java:

```<code>mPrefToken = getSharedPreferences(PREF_TOKEN, Context.MODE_PRIVATE);
fcmtoken = mPrefToken.getString(KEY_TOKEN, "");
if (fcmtoken.equals("")) {
    FirebaseInstallations.getInstance().getToken(true).addOnCompleteListener(new OnCompleteListener<InstallationTokenResult>() {
        @Override
        public void onComplete(@NonNull Task<InstallationTokenResult> task) {
            if(!task.isSuccessful()){
                return;
            }
            fcmtoken = task.getResult().getToken();
            mPrefToken.edit().putString(KEY_TOKEN, fcmtoken).apply();
            sendToken(user_id,fcmtoken);
        }
    });
} else {
    sendToken(user_id,fcmtoken);
}
</code>```

And in MyFirebaseMessagingService.java

```<code>@Override
public void onNewToken(String token) {
    super.onNewToken(token);
    mPrefToken = getSharedPreferences(PREF_TOKEN, Context.MODE_PRIVATE);
    mPrefToken.edit().putString(KEY_TOKEN, token).apply();
}
</code>```

I'm using the latest Android Studio (4.2.2 and build gradle com.android.tools.build:gradle:4.2.2) but have been experiencing this issue since 4.1.x as far as I can remember. My app is targeting SDK 23 - 30.

I'm using buildToolsVersion "30.0.3" but I believe I've been experiencing this since 30.0.2

FCM version is com.google.firebase:firebase-messaging:22.0.0. Have tried with 21.0.0 but experienced the same thing.

答: Don't pass .getToken(true) refresh, but .getToken(false) refresh.

Title: FCM intermittenly generates wrong token

Body:
I have tried to search the solutions everywhere, like several links below but couldn't find any correct answer.

FCM token Not Generating

What is FCM token in Firebase?

Firebase FCM force onTokenRefresh() to be called

The problem is every time I tried doing fresh install, both from Android Studio and Play Store, FCM sometimes generates a right token, but sometimes it generarates a wrong token. Whilst the right token is always different, the wrong token is always the same, starting with eyJhb. I know this info is useless since FCM generates the token based on device ID and app ID.

I've forced FCM to generate the token using this code in my LoginActivity.java:

mPrefToken = getSharedPreferences(PREF_TOKEN, Context.MODE_PRIVATE);
fcmtoken = mPrefToken.getString(KEY_TOKEN, "");
if (fcmtoken.equals("")) {
    FirebaseInstallations.getInstance().getToken(true).addOnCompleteListener(new OnCompleteListener<InstallationTokenResult>() {
        @Override
        public void onComplete(@NonNull Task<InstallationTokenResult> task) {
            if(!task.isSuccessful()){
                return;
            }
            fcmtoken = task.getResult().getToken();
            mPrefToken.edit().putString(KEY_TOKEN, fcmtoken).apply();
            sendToken(user_id,fcmtoken);
        }
    });
} else {
    sendToken(user_id,fcmtoken);
}

And in MyFirebaseMessagingService.java

@Override
public void onNewToken(String token) {
    super.onNewToken(token);
    mPrefToken = getSharedPreferences(PREF_TOKEN, Context.MODE_PRIVATE);
    mPrefToken.edit().putString(KEY_TOKEN, token).apply();
}

I'm using the latest Android Studio (4.2.2 and build gradle com.android.tools.build:gradle:4.2.2) but have been experiencing this issue since 4.1.x as far as I can remember. My app is targeting SDK 23 - 30.

I'm using buildToolsVersion "30.0.3" but I believe I've been experiencing this since 30.0.2

FCM version is com.google.firebase:firebase-messaging:22.0.0. Have tried with 21.0.0 but experienced the same thing.


问:
C# - Get Second to Last Item in a List
I have some code written in C#. In this code, I have a List<KeyValuePair<int, string>> items. I am trying to get the second-to-last item in the list. I'm having problems doing it though.

Originally, my collection was just a Dictionary<int, string>. At that point, I was using:

```<code>var nextToLast = items.Reverse().Skip(1).FirstOrDefault();
</code>```

That worked. However, since items is now a List<KeyValuePair<int, string>>, the Reverse method returns a void. So, I can't do the skip.

Anyone know of an elegant way for me to get the second-to-last item from a List<KeyValuePair<int, string>> in C#?

I know I can use a loop. I just figured there had to be a better way.

答:
```<code>        public IList<string> newList = new List<string>();
    public void OnGet()
    {
        var list = new List<string> { "one", "two", "three", "four" };
        list.RemoveAt(0);
        while (list.Count != 0)
        {
            var index = list.Next(0, list.Count);
            newlist.Add(list[index]);
            list.RemoveAt(index);
        }
    }
</code>```

@Model.newList[0]

@Model.newList[1]

@Model.newList[2]

```

Title: C# - Get Second to Last Item in a List

Body:
I have some code written in C#. In this code, I have a List<KeyValuePair<int, string>> items. I am trying to get the second-to-last item in the list. I'm having problems doing it though.

Originally, my collection was just a Dictionary<int, string>. At that point, I was using:

var nextToLast = items.Reverse().Skip(1).FirstOrDefault();

That worked. However, since items is now a List<KeyValuePair<int, string>>, the Reverse method returns a void. So, I can't do the skip.

Anyone know of an elegant way for me to get the second-to-last item from a List<KeyValuePair<int, string>> in C#?

I know I can use a loop. I just figured there had to be a better way.

Body:
        public IList<string> newList = new List<string>();
    public void OnGet()
    {
        var list = new List<string> { "one", "two", "three", "four" };
        list.RemoveAt(0);
        while (list.Count != 0)
        {
            var index = list.Next(0, list.Count);
            newlist.Add(list[index]);
            list.RemoveAt(index);
        }
    }

<tr>
<td>
@Model.newList[0]
<td>
<br />
<td>
@Model.newList[1]
<td>
<br />
<td>
@Model.newList[2]
<td>
<br />
</tr>


问:
Pass contents of file as a string to an argument for another command
I have a json file like this:

```<code>{"my_string": "apple", "my_int": 456}
</code>```

And a Bash program that works OK like this:

```<code>my_program --message='{"my_string": "apple", "my_int": 456}'
</code>```

But when my JSON is a file I cannot seem to get it to run properly:

```<code>my_program --message=$(cat test_message.json)
</code>```

I've been searching SO looking at similar questions and have tried lots of things like tr, awk, and various combinations of echo and cat but to no avail.

This is the error I receive that leads me to believe this is something I am doing wrong in Bash:

```<code>ERROR: (gcloud.beta.pubsub.schemas.validate-message) unrecognized arguments:
  "apple",
  "my_int":
  456}
  To search the help text of gcloud commands, run:
  gcloud help -- SEARCH_TERMS
</code>```

If you see it look like it has broken the JSON up, only taking the characters before the first space. Any ideas? I have a feeling this is very basic but I can't seem to figure it out. Thank you in advance.

答:
The immediate fix is to add quotes around the command substitution:

```<code>my_program --message="$(cat test_message.json)"
</code>```

See also When to wrap quotes around a shell variable?

However, a much better fix if you have control over my_program is to have it read standard input instead.

```<code>my_program --stdin <test_message.json
</code>```

If the cat is just a placeholder for something more complex, combine with a pipe:

```<code>jq .fnord test_message.json |
my_program --stdin
</code>```

(Maybe still better to not require an explicit option for this common base case.)

In case it's not obvious, the pipe is a direct line of communication between the producer and the consumer, whereas the command substitution requires the shell to read and buffer into memory all the output before passing it on. This is inefficient, inelegant, and slow and error-prone for any nontrivial amounts of output.

Body:
I have a json file like this:

{"my_string": "apple", "my_int": 456}

And a Bash program that works OK like this:

my_program --message='{"my_string": "apple", "my_int": 456}'

But when my JSON is a file I cannot seem to get it to run properly:

my_program --message=$(cat test_message.json)

I've been searching SO looking at similar questions and have tried lots of things like tr, awk, and various combinations of echo and cat but to no avail.

This is the error I receive that leads me to believe this is something I am doing wrong in Bash:

ERROR: (gcloud.beta.pubsub.schemas.validate-message) unrecognized arguments:
  "apple",
  "my_int":
  456}
  To search the help text of gcloud commands, run:
  gcloud help -- SEARCH_TERMS

If you see it look like it has broken the JSON up, only taking the characters before the first space. Any ideas? I have a feeling this is very basic but I can't seem to figure it out. Thank you in advance.

Body:
The immediate fix is to add quotes around the command substitution:

my_program --message="$(cat test_message.json)"

See also When to wrap quotes around a shell variable?

However, a much better fix if you have control over my_program is to have it read standard input instead.

my_program --stdin <test_message.json

If the cat is just a placeholder for something more complex, combine with a pipe:

jq .fnord test_message.json |
my_program --stdin

(Maybe still better to not require an explicit option for this common base case.)

In case it's not obvious, the pipe is a direct line of communication between the producer and the consumer, whereas the command substitution requires the shell to read and buffer into memory all the output before passing it on. This is inefficient, inelegant, and slow and error-prone for any nontrivial amounts of output.


问:
Adding "Sale" product category to products that are on sale in Woocommerce
As part of a WooCommerce site I want to have a sale page that lists sale items (with pagination and filtering). I think the best way to do this is to have a 'Sale' category that is added automatically to any posts that are part of the sale (as category pages allow for filtering and pagination automatically.

I have this code so far to programatically add the sale category to products when you save them:

```<code>function update_test( $product) {
wp_set_object_terms($product, 'sale', 'product_cat', true );
}

add_action( 'save_post', 'update_test', 1, 2);`
</code>```

However, I only want this to happen if a product is on sale (i.e has sale price set) so that saving posts that are not on sale does not add the sale category. I have tried several different things, but have had no luck. I tried this, but it didnt work:

```<code>function update_test( $product ) {
if($product->is_on_sale()){
wp_set_object_terms($product, 'sale', 'product_cat', true );
}
}

add_action( 'save_post', 'update_test', 1, 2);`
</code>```

but this just made my site freeze on save.

Any ideas?

Andy

答:
I think a more convenient way of doing this, that also works on variable products, would be adding the following in child theme's function.php (or via a plugin, etc):

```<code>add_action( 'woocommerce_update_product', 'update_product_set_sale_cat', 10, 2 );

function update_product_set_sale_cat( $product_id, $product ) {
    if ( $product->is_on_sale() ) {
        wp_add_object_terms($product_id, "sale", 'product_cat');
    } else { // this will also remove the sale category when the product in no longer on sale
        wp_remove_object_terms($product_id, "sale", 'product_cat');
    }
}
</code>```

It uses the woocommerce_update_product hook which runs whenever a product is updated/created in the database.

Body:
As part of a WooCommerce site I want to have a sale page that lists sale items (with pagination and filtering). I think the best way to do this is to have a 'Sale' category that is added automatically to any posts that are part of the sale (as category pages allow for filtering and pagination automatically.

I have this code so far to programatically add the sale category to products when you save them:

function update_test( $product) {
wp_set_object_terms($product, 'sale', 'product_cat', true );
}

add_action( 'save_post', 'update_test', 1, 2);`

However, I only want this to happen if a product is on sale (i.e has sale price set) so that saving posts that are not on sale does not add the sale category. I have tried several different things, but have had no luck. I tried this, but it didnt work:

function update_test( $product ) {
if($product->is_on_sale()){
wp_set_object_terms($product, 'sale', 'product_cat', true );
}
}

add_action( 'save_post', 'update_test', 1, 2);`

but this just made my site freeze on save.

Any ideas?

Andy

Body:
I think a more convenient way of doing this, that also works on variable products, would be adding the following in child theme's function.php (or via a plugin, etc):

add_action( 'woocommerce_update_product', 'update_product_set_sale_cat', 10, 2 );

function update_product_set_sale_cat( $product_id, $product ) {
    if ( $product->is_on_sale() ) {
        wp_add_object_terms($product_id, "sale", 'product_cat');
    } else { // this will also remove the sale category when the product in no longer on sale
        wp_remove_object_terms($product_id, "sale", 'product_cat');
    }
}

It uses the woocommerce_update_product hook which runs whenever a product is updated/created in the database.


问:
iPhone MessageUI email attachments not being sent to receiver
I am trying to attach an image and a pdf to an email using the MessageUI framework. I followed the MailComposer example in the Apple documentation.

On the iPhone it seems to work perfectly, the image and the pdf both show up in the body of the send mail window as expected.

However, when I receive the email on my MacBook there are two problems.

1) myImage.png shows up as an attachment and is the correct dimensions but is totally blank

2) myPDF.pdf doesn't show up as an attachment at all

But, when I receive the mail on my iPhone, myImage.png shows up fine. myPDF.pdf still doesn't show up in mail on my iPhone though.

Hope someone can shed some light on what might be happening.

Here is the relevant code:

```<code>MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;

[picker setSubject:@"Test Email"];

 // Attach an image to the email
 NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"myImage" ofType:@"png"];
 NSData *imageData = [NSData dataWithContentsOfFile:imagePath];
 [picker addAttachmentData:imageData mimeType:@"image/png" fileName:@"myImage"];

// Attach a PDF file to the email
NSString *pdfPath = [[NSBundle mainBundle] pathForResource:@"myPDF" ofType:@"pdf"];
NSData *pdfData = [NSData dataWithContentsOfFile:pdfPath];
[picker addAttachmentData:pdfData mimeType:@"application/pdf" fileName:@"myPDF"];

// Fill out the email body text
NSString *emailBody = @"This is a test.";
[picker setMessageBody:emailBody isHTML:NO];

[self presentModalViewController:picker animated:YES];
[picker release];
</code>```

EDIT Instead of saving and retrieving my image and PDF to my mainBundle I used NSDocumentsDirectory and everything worked fine.

答:
Try This ,This one worked for me .</p>

```<code>MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;

[picker setSubject:@"Test Email"];

 // Attach an image to the email
 NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"myImage" ofType:@"png"];
 NSData *imageData = [NSData dataWithContentsOfFile:imagePath];
 [picker addAttachmentData:imageData mimeType:@"image/png" fileName:@"myImage"];

// Attach a PDF file to the email
//NSString *pdfPath = [[NSBundle mainBundle] pathForResource:@"myPDF" ofType:@"pdf"];
//NSData *pdfData = [NSData dataWithContentsOfFile:pdfPath];

[picker addAttachmentData:pdfData mimeType:@"application/pdf" fileName:@"myPDF.pdf"];

// Fill out the email body text
NSString *emailBody = @"This is a test.";
[picker setMessageBody:emailBody isHTML:NO];

   // [self presentModalViewController:picker animated:YES];

    [picker release];
</code>```

ContentLicense: CC BY-SA 2.5

Body:
I am trying to attach an image and a pdf to an email using the MessageUI framework. I followed the MailComposer example in the Apple documentation.

On the iPhone it seems to work perfectly, the image and the pdf both show up in the body of the send mail window as expected.

However, when I receive the email on my MacBook there are two problems.

1) myImage.png shows up as an attachment and is the correct dimensions but is totally blank

2) myPDF.pdf doesn't show up as an attachment at all

But, when I receive the mail on my iPhone, myImage.png shows up fine. myPDF.pdf still doesn't show up in mail on my iPhone though.

Hope someone can shed some light on what might be happening.

Here is the relevant code:

MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;

[picker setSubject:@"Test Email"];

 // Attach an image to the email
 NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"myImage" ofType:@"png"];
 NSData *imageData = [NSData dataWithContentsOfFile:imagePath];
 [picker addAttachmentData:imageData mimeType:@"image/png" fileName:@"myImage"];

// Attach a PDF file to the email
NSString *pdfPath = [[NSBundle mainBundle] pathForResource:@"myPDF" ofType:@"pdf"];
NSData *pdfData = [NSData dataWithContentsOfFile:pdfPath];
[picker addAttachmentData:pdfData mimeType:@"application/pdf" fileName:@"myPDF"];

// Fill out the email body text
NSString *emailBody = @"This is a test.";
[picker setMessageBody:emailBody isHTML:NO];

[self presentModalViewController:picker animated:YES];
[picker release];

EDIT Instead of saving and retrieving my image and PDF to my mainBundle I used NSDocumentsDirectory and everything worked fine.

Body:
Try This ,This one worked for me .

MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;

[picker setSubject:@"Test Email"];

 // Attach an image to the email
 NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"myImage" ofType:@"png"];
 NSData *imageData = [NSData dataWithContentsOfFile:imagePath];
 [picker addAttachmentData:imageData mimeType:@"image/png" fileName:@"myImage"];

// Attach a PDF file to the email
//NSString *pdfPath = [[NSBundle mainBundle] pathForResource:@"myPDF" ofType:@"pdf"];
//NSData *pdfData = [NSData dataWithContentsOfFile:pdfPath];

[picker addAttachmentData:pdfData mimeType:@"application/pdf" fileName:@"myPDF.pdf"];

// Fill out the email body text
NSString *emailBody = @"This is a test.";
[picker setMessageBody:emailBody isHTML:NO];

   // [self presentModalViewController:picker animated:YES];

    [picker release];


问:
What is the reason for returning undefined voluntarily?
Why would you want to return undefined?
for example in this discord.js code example

```<code>client.on('interactionCreate', async interaction => {
if (!interaction.isCommand()) return;

const { commandName } = interaction;

if (commandName === 'ping') {
    await interaction.reply('Pong!');
} else if (commandName === 'server') {
    await interaction.reply('Server info.');
} else if (commandName === 'user') {
    await interaction.reply('User info.');
}
});
</code>```

Isn't returning undefined usually a sign something is wrong? So why would I return undefined voluntarily?
Any clearer examples would be greatly appreciated.

答:
This isn't about returning undefined, the return statement is simply a guard clause.
Guard clauses serve the main purpose to exit a function if certain criteria aren't met.

In this case, the reason for the guard clause is to only allow command interactions to go through, and to simply ignore button or selectmenu interactions.

Body:
Why would you want to return undefined?
for example in this discord.js code example

client.on('interactionCreate', async interaction => {
if (!interaction.isCommand()) return;

const { commandName } = interaction;

if (commandName === 'ping') {
    await interaction.reply('Pong!');
} else if (commandName === 'server') {
    await interaction.reply('Server info.');
} else if (commandName === 'user') {
    await interaction.reply('User info.');
}
});

Isn't returning undefined usually a sign something is wrong? So why would I return undefined voluntarily?
Any clearer examples would be greatly appreciated.