2015-10-27 2 views
0

Я хотел создать аватар для разговора, используя tts Android и выдвижную фрейм-аннуляцию в Android. Изображения синхронизации губ были сохранены в папке с возможностью копирования. И это часть функции, которая выполняется при нажатии кнопки разговора.Кадр за кадром анимация Android

Суть функции в том, что на основе букв, каждое соответствующее действие синхронизации губ добавляется в анимацию. Остальные действия основаны на выбранном для выступления языке, решаются шаг и речевая скорость. Thread используется для запуска анимации и голоса параллельно.

 b1.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      //thread to add the animation 
      Thread avatarSp = new Thread(new Runnable() { 
       @Override 
       public void run() { 
        String toSpeak = ed1.getText().toString(); 
        String[] words = toSpeak.split(" "); 
        for (String word : words) { 
         word = word.toLowerCase(); 
         char[] letters = word.toCharArray(); 
         for (int i = 0; i < letters.length; i++) { 
          if (letters[i] == 'a') { 
           if (sr1 == 1) 
            avatarSpeak.addFrame(getResources().getDrawable(R.drawable.a_i), 500); 
           else if (sr1 == 2) 
            avatarSpeak.addFrame(getResources().getDrawable(R.drawable.a_i), 750); 
          } else if (letters[i] == 'e') { 
           if (letters[i + 1] == 'i' || letters[i + 1] == 'a' || letters[i + 1] == 'e') { 
            i++; 
            if (sr1 == 1) 
             avatarSpeak.addFrame(getResources().getDrawable(R.drawable.e), 500); 
            else if (sr1 == 2) 
             avatarSpeak.addFrame(getResources().getDrawable(R.drawable.e), 750); 
           } else { 
            if (sr1 == 1) 
             avatarSpeak.addFrame(getResources().getDrawable(R.drawable.l), 500); 
            else if (sr1 == 2) 
             avatarSpeak.addFrame(getResources().getDrawable(R.drawable.l), 750); 
           } 

          } else if (letters[i] == 'i') { 
           if (sr1 == 1) 
            avatarSpeak.addFrame(getResources().getDrawable(R.drawable.c_d_g_k_n_r_s_th_y_z), 500); 
           else if (sr1 == 2) 
            avatarSpeak.addFrame(getResources().getDrawable(R.drawable.c_d_g_k_n_r_s_th_y_z), 750); 

          } else if (letters[i] == 'o') { 
           if (sr1 == 1) 
            avatarSpeak.addFrame(getResources().getDrawable(R.drawable.o), 500); 
           else if (sr1 == 2) 
            avatarSpeak.addFrame(getResources().getDrawable(R.drawable.o), 750); 
          } else if (letters[i] == 'u') { 
           if (sr1 == 1) 
            avatarSpeak.addFrame(getResources().getDrawable(R.drawable.u), 500); 
           else if (sr1 == 2) 
            avatarSpeak.addFrame(getResources().getDrawable(R.drawable.u), 750); 
          } else if (letters[i] == 'w' || letters[i] == 'q') { 
           if (sr1 == 1) 
            avatarSpeak.addFrame(getResources().getDrawable(R.drawable.w_q), 500); 
           else if (sr1 == 2) 
            avatarSpeak.addFrame(getResources().getDrawable(R.drawable.w_q), 750); 
          } else if (letters[i] == 'f' || letters[i] == 'v') { 
           if (sr1 == 1) 
            avatarSpeak.addFrame(getResources().getDrawable(R.drawable.f_v), 500); 
           else if (sr1 == 2) 
            avatarSpeak.addFrame(getResources().getDrawable(R.drawable.f_v), 750); 
          } else if (letters[i] == 'l') { 
           if (sr1 == 1) 
            avatarSpeak.addFrame(getResources().getDrawable(R.drawable.l), 500); 
           else if (sr1 == 2) 
            avatarSpeak.addFrame(getResources().getDrawable(R.drawable.l), 750); 
          } else if (letters[i] == 'm' || letters[i] == 'b' || letters[i] == 'p') { 
           if (sr1 == 1) 
            avatarSpeak.addFrame(getResources().getDrawable(R.drawable.m_b_p), 500); 
           else if (sr1 == 2) 
            avatarSpeak.addFrame(getResources().getDrawable(R.drawable.m_b_p), 750); 
          } else { 
           if (sr1 == 1) 
            avatarSpeak.addFrame(getResources().getDrawable(R.drawable.c_d_g_k_n_r_s_th_y_z), 500); 
           else if (sr1 == 2) 
            avatarSpeak.addFrame(getResources().getDrawable(R.drawable.c_d_g_k_n_r_s_th_y_z), 750); 
          } 
         } 
         if (sr1 == 1) 
          avatarSpeak.addFrame(getResources().getDrawable(R.drawable.rest), 500); 
         else if (sr1 == 2) 
          avatarSpeak.addFrame(getResources().getDrawable(R.drawable.rest), 750); 
        } 
        avatar.post(new Starter()); 
       } 

      }); 
      //start the thread 
      avatarSp.start(); 
      tts1.setPitch(p1); 
      tts1.setSpeechRate(sr1); 
      String toSpeak = ed1.getText().toString(); 
      lang = sp1.getSelectedItem().toString(); 
      if (lang.equals("US")) { 
       System.out.print("Condition satisfied"); 
       tts1.setLanguage(Locale.US); 
      } else if (lang.equals("UK")) 
       tts1.setLanguage(Locale.UK); 
      else if (lang.equals("Germany")) 
       tts1.setLanguage(Locale.GERMANY); 
      else if (lang.equals("Italy")) 
       tts1.setLanguage(Locale.ITALY); 
      else if (lang.equals("Japan")) 
       tts1.setLanguage(Locale.JAPAN); 
      else 
       tts1.setLanguage(Locale.CHINA); 

      Toast.makeText(getApplicationContext(), toSpeak, Toast.LENGTH_SHORT).show(); 
      //speak 
      tts1.speak(toSpeak, TextToSpeech.QUEUE_FLUSH, null); 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
       tts1.speak(toSpeak, TextToSpeech.QUEUE_FLUSH, null, null); 
      } else { 
       tts1.speak(toSpeak, TextToSpeech.QUEUE_FLUSH, null); 
      } 
     } 
    }); 
} 

Уровень API, на котором протестирован весь код, был Android 5.0 (21) и Android 6.0 (AVD 23). Но когда я нажимаю кнопку «говорить», API сбой, как на AVD, так и на телефоне. Можете ли вы сказать мне:

1. Where the error could possibly be? 
    2. Is there a better way to do this and how? 

Пожалуйста, медведь со мной, если его послушником, но я действительно хотел бы знать лучшие способы сделать достижение функции, в моем собственном коде.

UPDATE 1

Информационный кот журнал добавляется.

10-29 09:02:26.245 1931-1931/com.bluesbegone.avatarspeak I/art﹕ Not late-enabling -Xcheck:jni (already on) 
    10-29 09:02:26.246 1931-1931/com.bluesbegone.avatarspeak I/art﹕ Late-enabling JIT 
    10-29 09:02:26.411 1931-1931/com.bluesbegone.avatarspeak I/art﹕ JIT created with code_cache_capacity=2MB compile_threshold=1000 
    10-29 09:02:27.282 1931-1931/com.bluesbegone.avatarspeak W/System﹕ ClassLoader referenced unknown path: /data/app/com.bluesbegone.avatarspeak-2/lib/x86 
    10-29 09:02:28.992 1931-1931/com.bluesbegone.avatarspeak I/TextToSpeech﹕ Sucessfully bound to com.svox.pico 
    10-29 09:02:29.026 1931-1956/com.bluesbegone.avatarspeak D/OpenGLRenderer﹕ Use EGL_SWAP_BEHAVIOR_PRESERVED: true 
    10-29 09:02:29.056 1931-1931/com.bluesbegone.avatarspeak D/﹕ HostConnection::get() New Host Connection established 0xa3fff460, tid 1931 
    10-29 09:02:29.300 1931-1938/com.bluesbegone.avatarspeak W/art﹕ Suspending all threads took: 37.049ms 
    10-29 09:02:29.459 1931-1956/com.bluesbegone.avatarspeak D/﹕ HostConnection::get() New Host Connection established 0xa3fff830, tid 1956 
    10-29 09:02:29.509 1931-1956/com.bluesbegone.avatarspeak I/OpenGLRenderer﹕ Initialized EGL, version 1.4 
    10-29 09:02:29.671 1931-1956/com.bluesbegone.avatarspeak W/EGL_emulation﹕ eglSurfaceAttrib not implemented 
    10-29 09:02:29.672 1931-1956/com.bluesbegone.avatarspeak W/OpenGLRenderer﹕ Failed to set EGL_SWAP_BEHAVIOR on surface 0xad77ac60, error=EGL_SUCCESS 
    10-29 09:02:29.912 1931-1931/com.bluesbegone.avatarspeak I/Choreographer﹕ Skipped 41 frames! The application may be doing too much work on its main thread. 
    10-29 09:02:31.082 1931-1931/com.bluesbegone.avatarspeak I/Choreographer﹕ Skipped 69 frames! The application may be doing too much work on its main thread. 
    10-29 09:02:31.297 1931-1931/com.bluesbegone.avatarspeak I/TextToSpeech﹕ Connected to ComponentInfo{com.svox.pico/com.svox.pico.PicoService} 
    10-29 09:02:31.822 1931-1968/com.bluesbegone.avatarspeak I/TextToSpeech﹕ Set up connection to ComponentInfo{com.svox.pico/com.svox.pico.PicoService} 
    10-29 09:02:32.280 1931-1938/com.bluesbegone.avatarspeak W/art﹕ Suspending all threads took: 288.632ms 
    10-29 09:02:35.320 1931-1938/com.bluesbegone.avatarspeak W/art﹕ Suspending all threads took: 12.137ms 
    10-29 09:02:43.335 1931-2173/com.bluesbegone.avatarspeak E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-83 
Process: com.bluesbegone.avatarspeak, PID: 1931 
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 
     at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6556) 
     at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:942) 
     at android.view.ViewGroup.invalidateChild(ViewGroup.java:5081) 
     at android.view.View.invalidateInternal(View.java:12713) 
     at android.view.View.invalidate(View.java:12649) 
     at android.view.View.invalidateDrawable(View.java:16788) 
     at android.widget.ImageView.invalidateDrawable(ImageView.java:248) 
     at android.graphics.drawable.DrawableContainer.invalidateDrawable(DrawableContainer.java:377) 
     at android.graphics.drawable.Drawable.invalidateSelf(Drawable.java:385) 
     at android.graphics.drawable.Drawable.setVisible(Drawable.java:764) 
     at android.graphics.drawable.DrawableContainer.initializeDrawableForDisplay(DrawableContainer.java:510) 
     at android.graphics.drawable.DrawableContainer.selectDrawable(DrawableContainer.java:459) 
     at android.graphics.drawable.AnimationDrawable.setFrame(AnimationDrawable.java:274) 
     at android.graphics.drawable.AnimationDrawable.addFrame(AnimationDrawable.java:251) 
     at com.bluesbegone.avatarspeak.MainActivity$4$1.run(MainActivity.java:190) 
     at java.lang.Thread.run(Thread.java:818) 
    10-29 09:02:44.093 1931-1942/com.bluesbegone.avatarspeak I/art﹕ Background sticky concurrent mark sweep GC freed 10741(781KB) AllocSpace objects, 0(0B) LOS objects, 39% free, 2MB/3MB, paused 1.490ms total 313.129ms 
    10-29 09:02:44.122 1931-1942/com.bluesbegone.avatarspeak W/art﹕ Suspending all threads took: 26.447ms 
    10-29 09:02:44.278 1931-1938/com.bluesbegone.avatarspeak W/art﹕ Suspending all threads took: 146.147ms 
    10-29 09:02:45.073 1931-1931/com.bluesbegone.avatarspeak I/Choreographer﹕ Skipped 77 frames! The application may be doing too much work on its main thread. 
    10-29 09:02:45.160 1931-1956/com.bluesbegone.avatarspeak W/EGL_emulation﹕ eglSurfaceAttrib not implemented 
    10-29 09:02:45.161 1931-1956/com.bluesbegone.avatarspeak W/OpenGLRenderer﹕ Failed to set EGL_SWAP_BEHAVIOR on surface 0xa29586e0, error=EGL_SUCCESS 
    10-29 09:02:45.231 1931-1956/com.bluesbegone.avatarspeak E/Surface﹕ getSlotFromBufferLocked: unknown buffer: 0xab81f1e0 
    10-29 09:02:47.005 1931-1956/com.bluesbegone.avatarspeak E/Surface﹕ getSlotFromBufferLocked: unknown buffer: 0xab81f1e0 
    10-29 09:02:48.334 1931-2173/com.bluesbegone.avatarspeak I/Process﹕ Sending signal. PID: 1931 SIG: 9 
+2

Что делает лог-шоу? – Chris

+0

@ Спасибо за ваш ответ. Извините за то, что вы не вернулись раньше, и, пожалуйста, проверьте свое изменение. Дайте мне знать, достаточно ли данных. –

+0

@ Крис не может понять многое из логарифма. некоторые направления могут быть действительно полезными и для будущего. –

ответ

1

Вы пытаетесь анимировать вид из фоновой нити, но только основной поток может касаться представлений. Избавьтесь от потока и просто поместите код в основной метод onClick.

+0

Дело в том, что я хочу, чтобы анимация и речь запускались в одно и то же время. Сроки должны быть согласованы. Как я могу достичь этой, если не параллельной обработки? Можете ли вы предложить лучший способ для анимации, которую я пытаюсь сделать? –

+0

Удаление темы помогло @Chris. Но я столкнулся с несколькими проблемами. –

Смежные вопросы