2016-04-12 5 views
0

Erstellen einer App, die einen EditText-Wert annimmt und diesen in Morse-Code übersetzt und Audio ausgibt, während eine TextView-Hintergrundfarbe geändert wird, um die Aufgabe zu bearbeiten. Die Audio- und TextView-Farbänderung soll zusammen erfolgen.
ich diese Klasse mit MorseTask.java die ich glaube, ist mir die meisten Probleme verursacht:Morsecode-Anwendung AsyncTask Error 5

public class MorseTask extends AsyncTask<String, Integer, Void> { 
private String translate; 

@Override 
protected Void doInBackground(String... params) { 

    translate = params[0]; 
    int hold = 500; 
    LinkedList<Signal> signals = MorseCode.genOnOffSchedule(translate, hold); 
    long start = System.currentTimeMillis(); 

    while (!signals.isEmpty()){ 
     Signal sig = signals.removeFirst(); 
     boolean landed = false; 
     while(!landed){ 
      landed = (System.currentTimeMillis() - start) > sig.getOnset(); 
      flashUI(sig); 
     } 
    } 
    return null; 
} 
//TODO this 
public void flashUI(Signal signal){ 
    int flashColor = Color.rgb(255, 255, 255); 
    int oldColor = Color.rgb(2, 2, 2); 
    if(signal.isOn()){ 
     publishProgress(1); 
     MainActivity.textView2.setBackgroundColor(flashColor); 
     int toneHrzt = 440; 
     AudioTrack sound = AudioUtils.generateTone(toneHrzt, signal.getDuration()); 
     sound.play(); 
     //TODO this may need not null I'm not sure 
     if(sound == null){ 
      sound.release(); 
     } 
    } 
    else{ 
     publishProgress(0); 
     MainActivity.textView2.setBackgroundColor(oldColor); 

    } 
    try { 
     Thread.sleep(signal.getDuration()); 
    } catch (InterruptedException e) { 
     Thread.currentThread().interrupt(); 
    } 

} 
//TODO add something here probably a void param 
protected void onPostExecute(TextView result){ 
    //TODO reset the activity, possibly 


} 
} 
  • MorseCode.genOnOffSchedule(String, int) ist ein Verfahren, das im wesentlichen die Sequenz/Muster des Morsecode einrichtet.

  • Ich bin mir nicht sicher, wie man onPostExecute anders als möglicherweise die Aktivität zurücksetzen.

Hier ist meine MainActivity und wie ich die Ausführung der Aufgabe:

public class MainActivity extends AppCompatActivity { 
public static TextView textView2; 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    textView2 = (TextView)findViewById(R.id.textView2); 
    final EditText message = (EditText)findViewById(R.id.editText); 
    final Button translate = (Button)findViewById(R.id.button); 
    translate.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      String text = message.getText().toString(); 
      MorseTask transmit = new MorseTask(); 
      transmit.execute(text); 
     } 
    }); 
} 

}

Und schließlich meine logcat Fehler:

04-11 19:45:45.191 7815-7937/MYDOMAIN E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #5 
Process: MYDOMAIN, PID: 7815 
                 java.lang.RuntimeException: An error occured while executing doInBackground() 
                      at android.os.AsyncTask$3.done(AsyncTask.java:304) 
                      at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355) 
                      at java.util.concurrent.FutureTask.setException(FutureTask.java:222) 
                      at java.util.concurrent.FutureTask.run(FutureTask.java:242) 
                      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 
                      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
                      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
                      at java.lang.Thread.run(Thread.java:818) 
                     Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 
                      at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6357) 
                      at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:909) 
                      at android.view.ViewGroup.invalidateChild(ViewGroup.java:4690) 
                      at android.view.View.invalidateInternal(View.java:11801) 
                      at android.view.View.invalidate(View.java:11737) 
                      at android.view.View.invalidateDrawable(View.java:15825) 
                      at android.widget.TextView.invalidateDrawable(TextView.java:5129) 
                      at android.graphics.drawable.Drawable.invalidateSelf(Drawable.java:368) 
                      at android.graphics.drawable.ColorDrawable.setColor(ColorDrawable.java:134) 
                      at android.view.View.setBackgroundColor(View.java:16184) 
                      at edu.ggc.amauldin.morsecode.MorseTask.flashUI(MorseTask.java:45) 
                      at edu.ggc.amauldin.morsecode.MorseTask.doInBackground(MorseTask.java:34) 
                      at edu.ggc.amauldin.morsecode.MorseTask.doInBackground(MorseTask.java:18) 
                      at android.os.AsyncTask$2.call(AsyncTask.java:292) 
                      at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
                      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)  
                      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)  
                      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)  
                      at java.lang.Thread.run(Thread.java:818)  

Antwort

1

Diese Linien:

MainActivity.textView2.setBackgroundColor(flashColor); 
... 
MainActivity.textView2.setBackgroundColor(oldColor); 

werden in der flashUI()-Methode aufgerufen, die Sie von doInBackground() aufrufen, was bedeutet, dass sie in einem separaten Thread passiert. Sie können den Bildschirm View nicht aus einem beliebigen Thread außer dem Hauptthread berühren.

Verschieben Sie diese Zeilen in die Methode onProgressUpdate(), die auf dem Hauptthread ausgeführt wird.

+0

Sinn macht. Nur, wie kann ich sicherstellen, dass es blinkt, ohne FlashUI innerhalb der Bedingung, wo "signal.isOn()". Ich glaube nicht, dass ich wissen würde, welches Signal oder die Variable, die ich verwendet habe, "sig" gespielt wurde, um synchron mit dem Ton zu blinken. –

+0

Ich bin nicht ganz sicher, was Sie sagen, aber jedes Mal, wenn Sie 'setBackgroundColor()' aufrufen, rufen Sie 'publishProgress()' entweder mit '0' oder' 1' auf, also mit 'onProgressUpdate()' Überprüfen Sie den übergebenen Wert und legen Sie den Hintergrund entsprechend fest. Wenn '0' =>' oldColor', wenn '1' =>' flashColor'. –

+1

Ja, ich habe nicht festgestellt, was ich versucht habe zu vermitteln, aber überraschenderweise haben Sie meine Bedenken mit allen Widrigkeiten gegen Sie beantwortet. Vielen Dank! –