Categories
discuss

Android ToneGenerator startTone() very slow on the first call

I’m calling ToneGenerator.startTone() repeatedly to issue short bursts of sound. But on the first call, it blocks for a long period of time. So the first burst is way too long. Here’s an example:

Member variables:

private ToneGenerator mDTMFPlayer

In the constructor:

mDTMFPlayer = new ToneGenerator(AudioManager.STREAM_VOICE_CALL, TONE_RELATIVE_VOLUME);

In a Thread started by OnClickListener.onClick():

long startTime = System.currentTimeMillis();
mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
Log.d(TAG,"After 1st: " + (System.currentTimeMillis() - startTime));
try { Thread.sleep(160); } catch (InterruptedException e) { }
mDTMFPlayer.stopTone();

startTime = System.currentTimeMillis();
mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
Log.d(TAG,"After 2nd: " + (System.currentTimeMillis() - startTime));
try { Thread.sleep(160); } catch (InterruptedException e) { }
mDTMFPlayer.stopTone();

startTime = System.currentTimeMillis();
mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
Log.d(TAG,"After 3rd: " + (System.currentTimeMillis() - startTime));
try { Thread.sleep(160); } catch (InterruptedException e) { }
mDTMFPlayer.stopTone();

Here’s the output, with execution time of startTone() in milliseconds:

11-16 18:07:35.885 16927-17977/com.my.project D/Ring: After 1st: 454
11-16 18:07:36.502 16927-17977/com.my.project D/Ring: After 2nd: 0
11-16 18:07:36.672 16927-17977/com.my.project D/Ring: After 3rd: 1

The first call is blocking for almost half a second which is way too long for what I need. Any calls after that makes the blocking go away for a while. What’s weird is that if I wait a bit and try again, it’s slow again. There seems to be a period after which the blocking comes back.

Please advise.

Answer

I think that AudioManager.STREAM_VOICE_CALL is causing this. The behavior on my devise is similar to yours. After i run app it has long init for the first startTone() call. If i exit and enter app it can be fast for all 3 calls. But it will show same “slow, fast, fast” result if some system sound plays before the app starts.

So i suppose it has something to do with stream switching/blocking, because with AudioManager.STREAM_NOTIFICATION it takes only 4-10 msecs on my device. Also can read more info here: What is the difference between AudioManager’s stream types at low level?

Consider this code:

for (int i = -1; i < 10; i++) {
    System.out.println("AudioSystem stream " + i);
    mDTMFPlayer = new ToneGenerator(i, TONE_RELATIVE_VOLUME);
    long startTime = System.currentTimeMillis();
    mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
    Log.d(TAG, "After 1st: " + (System.currentTimeMillis() - startTime));
    try {Thread.sleep(160);} catch (InterruptedException e) {}
    mDTMFPlayer.stopTone();

    startTime = System.currentTimeMillis();
    mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
    Log.d(TAG, "After 2nd: " + (System.currentTimeMillis() - startTime));
    try {Thread.sleep(160);} catch (InterruptedException e) {}
    mDTMFPlayer.stopTone();

    startTime = System.currentTimeMillis();
    mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
    Log.d(TAG, "After 3rd: " + (System.currentTimeMillis() - startTime));
    try {Thread.sleep(160);} catch (InterruptedException e) {}
    mDTMFPlayer.stopTone();
    mDTMFPlayer.release();
}

Output:

I/System.out: AudioSystem stream -1 STREAM_DEFAULT
D/com.example.MainActivity: After 1st: 8
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 0 STREAM_VOICE_CALL
D/com.example.MainActivity: After 1st: 325
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 1 STREAM_SYSTEM
D/com.example.MainActivity: After 1st: 17
D/com.example.MainActivity: After 2nd: 2
D/com.example.MainActivity: After 3rd: 3
I/System.out: AudioSystem stream 2 STREAM_RING
D/com.example.MainActivity: After 1st: 28
D/com.example.MainActivity: After 2nd: 2
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 3 STREAM_MUSIC
D/com.example.MainActivity: After 1st: 19
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 4 STREAM_ALARM
D/com.example.MainActivity: After 1st: 28
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 5 STREAM_NOTIFICATION
D/com.example.MainActivity: After 1st: 16
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 6 STREAM_BLUETOOTH_SCO
D/com.example.MainActivity: After 1st: 332
D/com.example.MainActivity: After 2nd: 2
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 7 STREAM_SYSTEM_ENFORCED
D/com.example.MainActivity: After 1st: 324
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 8 STREAM_DTMF
D/com.example.MainActivity: After 1st: 26
D/com.example.MainActivity: After 2nd: 2
D/com.example.MainActivity: After 3rd: 4
I/System.out: AudioSystem stream 9 STREAM_TTS
D/com.example.MainActivity: After 1st: 12
D/com.example.MainActivity: After 2nd: 4
D/com.example.MainActivity: After 3rd: 2  

Btw, if you want to research related C sourse code you can look at android_media_ToneGenerator.cpp, ToneGenerator.h, ToneGenerator.cpp AudioService.java

Categories
discuss

Jenkins: FATAL: Could not initialize class hudson.util.ProcessTree$UnixReflection

FATAL: Could not initialize class hudson.util.ProcessTree$UnixReflection
java.lang.NoClassDefFoundError: Could not initialize class hudson.util.ProcessTree$UnixReflection
at hudson.util.ProcessTree$UnixProcess.kill(ProcessTree.java:647)
at hudson.util.ProcessTree$UnixProcess.killRecursively(ProcessTree.java:668)
at hudson.util.ProcessTree$UnixProcess.killRecursively(ProcessTree.java:667)
at hudson.util.ProcessTree$Unix.killAll(ProcessTree.java:589)
at hudson.Launcher$LocalLauncher.kill(Launcher.java:949)
at hudson.model.AbstractBuild$AbstractBuildExecution.run(AbstractBuild.java:502)
at hudson.model.Run.execute(Run.java:1737)
at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:43)
at hudson.model.ResourceController.execute(ResourceController.java:97)
at hudson.model.Executor.run(Executor.java:421)

Jenkins ver. 2.73.3 MacOSx

Doing an iOS build and upload to hockeyapp. The .ipa is created successfully, error seems to happen afterwards, seems like on the hockeyapp upload. I have an android project that works and uploads to hockeyapp successfully though.

Started getting this today after updating Jenkins and plugins. Was working before.

Any ideas?

Answer

happened to me when running an Android build (Jenkins build 2.86, I just downgraded from 2.87 or something slighlty newer, because of other fails)

Build step 'Invoke Gradle script' changed build result to SUCCESS
FATAL: Could not initialize class 
hudson.util.ProcessTree$UnixReflection
java.lang.NoClassDefFoundError: Could not initialize class 
hudson.util.ProcessTree$UnixReflection
at hudson.util.ProcessTree$UnixProcess.kill(ProcessTree.java:647)
at hudson.util.ProcessTree$UnixProcess.killRecursively(ProcessTree.java:668)
at hudson.util.ProcessTree$Unix.killAll(ProcessTree.java:589)
at hudson.Launcher$LocalLauncher.kill(Launcher.java:949)
at hudson.model.AbstractBuild$AbstractBuildExecution.run(AbstractBuild.java:510)
at hudson.model.Run.execute(Run.java:1724)
at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:43)
at hudson.model.ResourceController.execute(ResourceController.java:97)
at hudson.model.Executor.run(Executor.java:421)
Finished: FAILURE

first SUCCESS then FAILURE, hmm weeeird

I remembered that recently I have installed java 9 for experimenting, but still having java 8 set to usl/libexec/java_home, in my .zshrc like:

export JAVA_HOME=`/usr/libexec/java_home -v 1.8.0_152`

but that did not help at all, so I said goodbye to Java 9 with

sudo rm -rf /Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk

then went to Manage Jenkins -> Configure System -> Environment variables and added

/Library/Java/JavaVirtualMachines/jdk1.8.0_152.jdk/Contents/Home

as JAVA_HOME

after Jenkins restart my builds run like a charm

Categories
discuss

Spring controller: Content-Type for StreamingResponseBody

In search for the least amount of code to serve a BufferedImage (painted in a service-class) from a spring-mvc Controller, I came up with the following:

@GetMapping(value = "/image", produces = "image/png")
public StreamingResponseBody image() {
    BufferedImage canvas = service.createImage();
    return outputStream -> ImageIO.write(canvas, "png", outputStream);
}

So far, so good – using the image in HTML via <img src="/image"> works fine.

However, spring does not send any Content-Type header at all. Together with serving X-Content-Type-Options: nosniff in the response, this leads to garbage in the browser window when the image URL is opened directly.

How do I provide a content-type header in the most spring-friendly way (i.e. not using HttpServletResponse directly)?

Answer

You can wrap it in a ResponseEntity<...>, this allows you to easily modify all the parameters in the response through the response builder:

@GetMapping(value = "/image", produces = "image/png")
public ResponseEntity<StreamingResponseBody> image() {
    BufferedImage canvas = service.createImage();

    StreamingResponseBody stream = outputStream ->
            ImageIO.write(canvas, "png", outputStream);

    return ResponseEntity.ok()
        .contentType(MediaType.IMAGE_PNG)
        .body(stream);
}
Categories
discuss

Is it okay to treat the prevState argument of setState’s function as mutable?

I know this.state is not supposed to be modified directly, instead setState should be used.

From this I inferred that prevState should be also treated as immutable and instead setState should always look something like this:

this.setState((prevState) => {
  // Create a new object instance to return
  const state = { ...prevState };
  state.counter = state.counter + 1;
  return state;
});

Or with deeper nesting:

this.setState((prevState) => {
  // Create a new object instance to return
  const state = { ...prevState, counter: { ...prevState.counter } };
  state.counter.value = state.counter.value + 1;
  return state;
});

Or just a partial update like would be with setState({}) where easier and nicer to use:

this.setState((prevState) => ({ counter: prevState.counter + 1 }));

All of the above are obviously correct because they return a new instance, but then I came across this question where the accepted answer encourages mutating prevState without returning a new object instance (notice the code block in the question).

Something like this:

this.setState((prevState) => {
  prevState.flag = !prevState.flag;
  return prevState;
});

I found this to be a sketchy suggestion so I decided to test if the object instance references of prevState and this.state are the same:

(The JSFiddle)

class Test extends React.Component {
  state = { counter: 0 };

  onDemonstrateButtonClick = (event) => {
    this.setState((prevState) => {
      if (prevState === this.state) alert(`uh, yep`);
      prevState.counter++;
      return prevState;
    });
  };

  render() {
    return (
      <div>
        <button onClick={this.onDemonstrateButtonClick}>Demonstrate</button>
        {this.state.counter}
      </div>
    );
  }
}

Whadayaknow, they are! So which is it? Is the answer wrong and should I return a new object instance or return partial update as a new object or can I go wild and mutate the prevState argument directly? And if yes, how is this any different from mutating this.state directly?

Side note: TypeScript React typings do not mark the argument as ReadOnly which only adds to my confusion.

Answer

First Point

Is it okay to treat the prevState argument of setState’s function as mutable?

The answer is NO you should never mutate prevState, this is also clearly mentioned in react documentation in setState section

  • prevState is a reference to the previous state. It should not be directly mutated. Instead, changes should be represented by building a new object based on the input from prevState and props.

Second Point:

You tested prevState and this.state and they are the same, well actually they are not.

To figure out why they are actually different we need to know why prevState actually exist, and the answer is that setState function is asynchronous, thats why react js is giving us access to prevState lets check the example below where prevState != this.state

In the example below we will increment counter twice per click, but we will use 2 setState operations each one of them will increment the counter by 1.

Because setState is async you will notice that the second setState operation started before the first setState is finished this is where prevState is useful and here prevState and this.state are not equal.

I commented each line with a number denoting when this line is executed, this should explain why we need prevState and why it is different from this.state.

class App extends React.Component{
  constructor(props)
  {
    super(props);
    this.state = {
      counter : 1
    };
  }

  increment = () =>{
    this.setState((prevState , props) => {
      console.log("in first"); //3
      console.log(prevState);  //3
      console.log(this.state); //3
      if(prevState == this.state)
      {
         console.log("in first prevState == this.state");
      }
      return {
        counter : prevState.counter+1
      }
    } , ()=>{
      console.log("done updating first"); //5
    });


    console.log("after first"); //1

    this.setState((prevState, props) => {
      console.log("in second"); //4
      console.log(this.state);  //4
      console.log(prevState);   //4
      if (prevState == this.state) {
        console.log("in second prevState == this.state");
      }
      return {
        counter: prevState.counter + 1
      }
    } , () =>{
      console.log("done updating second"); //6
    });

    console.log("after second"); //2

  }

  render(){
    return (
      <div>
        <span>{this.state.counter}</span>
        <br/>
        <button onClick={this.increment} >increment</button>
      </div>
    )
  }
}

The Result from the above code is

"after first"
"after second"
"in first"
▶Object {counter: 1}
▶Object {counter: 1}
"in first prevState == this.state"
"in second"
▶Object {counter: 1}
▶Object {counter: 2}
"done updating first"
"done updating second"

The above code is fully working in this link, you can check the console.log result https://codesandbox.io/s/k325l485mr


The above example will correctly increment counter twice per click, if you want to break it change return statement in second setState

from

return {
    counter: prevState.counter + 1
}

to

return {
    counter: this.state.counter + 1
}

and you will find that the result is not correct each click will result in 1 increment which is not correct because we have 2 setState , this is because we didn’t use prevState and we used an incorrect this.state

Finally

I believe that the correct way to update the counter is

this.setState((prevState) => ({ counter: prevState.counter + 1 }));

Categories
discuss

React Router v4 vs benefits

Besides the ability to set an “activeClassName” and “activeStyle” on NavLink, is there any reason to use NavLink over Link when creating links to other routes on non-navigational elements (ie. not main nav in header or footer) on your site that don’t need an active state/class?

Answer

The official documentation is clear:

<NavLink>

A special version of the <Link> that will add styling attributes to the rendered element when it matches the current URL.

Thus, the answer is NO. There are no other reasons except the mentioned one.

Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..