2015-01-20 19 views
2

以下是我的設置。 我有一個livecard服務類,它執行一個異步任務來從外部獲取天氣和weatherforecast數據。 它還啓動了一個Pendingintent,其中兩個菜單項是「ShowForecast」&「Stop」如何從服務呼叫接收異步數據時更新Google Glass菜單

天氣數據在主屏幕上顯示到達時顯示。 但預測數據需要更長的時間。我想隱藏ShowForecast菜單,直到異步任務成功完成。

實現此目的的最佳方法是什麼?我讀過一些關於全局變量的內容,或者通過intent.putextra或直接更新卡片菜單。 我現在想的是在我的活動類中使用一個布爾值,它在onPrepareOptionsMenu中籤入並隱藏/顯示菜單。

但是,如何在異步任務完成時從Service類設置此布爾值? 以下是課堂片段。所有建議歡迎您致電! :)

public class LiveCardMenuActivity extends Activity { 

private static final String TAG = LiveCardMenuActivity.class.getSimpleName(); 
// default disabled menu 
private boolean menu_showForecast = false; 

@Override 
// in this method we hide/ show forecast menu, depending if the service has gotten the data 
public boolean onPrepareOptionsMenu(Menu menu) { 
    if(!menu_showForecast) { 
     menu.findItem(R.id.action_show_forecast).setVisible(false); 
    } 
    return super.onPrepareOptionsMenu(menu); 

... 

,並與異步任務

public class LiveCardService extends Service { 

private static final String TAG = LiveCardService.class.getSimpleName(); 

private static final String LIVE_CARD_TAG = "LiveCardService"; 
private LiveCard mLiveCard; 
private RemoteViews mLiveCardView; 

private final Handler mHandler = new Handler(); 
private final UpdateLiveCardRunnable mUpdateLiveCardRunnable = new UpdateLiveCardRunnable(); 
private static final long DELAY_MILLIS = 1000; 

// keep the weather info central, due to reuse and forecast cards 
private Weather weather = new Weather(); 
private WeatherForecast weatherForecast = new WeatherForecast(); 

@Override 
public IBinder onBind(Intent intent) { 
    return null; 
} 

@Override 
public void onCreate() { 
    super.onCreate(); 

    // and get the weather data & icon, async call 
    String loc = "id=2755420"; 
    JSONWeatherTask task = new JSONWeatherTask(); 
    task.execute(new String[]{loc}); 

    // including the weather forecast 
    JSONWeatherForecastTask taskForecast = new JSONWeatherForecastTask(); 
    taskForecast.execute(new String[]{loc}); 
} 

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 
    if (mLiveCard == null) { 
     // Get an instance of a live card 
     mLiveCard = new LiveCard(this, LIVE_CARD_TAG); 

     // setup live card views 
     mLiveCardView = new RemoteViews(getPackageName(), R.layout.live_card); 
     mLiveCard.setViews(mLiveCardView); 

     // Display the options menu when the live card is tapped. 
     Intent menuIntent = new Intent(this, LiveCardMenuActivity.class); 
     mLiveCard.setAction(PendingIntent.getActivity(this, 0, menuIntent, 0)); 
     mLiveCard.publish(PublishMode.REVEAL); 

     // Queue the update text runnable 
     mHandler.post(mUpdateLiveCardRunnable); 
    } else { 
     mLiveCard.navigate(); 
    } 
    return START_STICKY; 
} 

... 

private class JSONWeatherForecastTask extends AsyncTask<String, Void, WeatherForecast> { 

    @Override 
    protected WeatherForecast doInBackground(String... params) { 
     // 
     String data = ((new WeatherHttpClient()).getWeatherForecastData(params[0])); 

     try { 
      weatherForecast = JSONWeatherForecastParser.getWeatherForecast(data); 
     } catch (JSONException e) { 
      e.printStackTrace(); 
     } 
     return weatherForecast; 
    } 

    @Override 
    protected void onPostExecute(WeatherForecast weatherForecast) { 
     super.onPostExecute(weatherForecast); 


     // there is no showing of data yet, except voor enabling the forecast menu 
     Weather[] weatherForecastArray = weatherForecast.getWeatherForecastArray(); 
     int count = weatherForecastArray.length; 
     if(count > 0){ 
      //mLiveCard menu update or boolean update? 
     } 
    } 

} 

回答

1

Timer sample的菜單Activity有一定的邏輯根據定時器運行的狀態動態地改變它的選項菜單中的服務類:

  1. MenuActivityonCreate回調:綁定到TimerService
  2. 一旦Service被綁定,檢索有關當前Timer的信息。
  3. 一旦所有狀態都滿足(Activity已附加到Window,已獲取計時器信息):打開選項菜單。

下面是從MenuActivity類的代碼片段:

/** 
* This activity manages the options menu that appears when the user taps on the timer's live 
* card or says "ok glass" while the live card is settled. 
*/ 
public class MenuActivity extends Activity { 

    private Timer mTimer; 
    private boolean mAttachedToWindow; 
    private boolean mIsMenuClosed; 
    private boolean mPreparePanelCalled; 
    private boolean mIsSettingTimer; 

    private boolean mFromLiveCardVoice; 

    private ServiceConnection mConnection = new ServiceConnection() { 
     @Override 
     public void onServiceConnected(ComponentName name, IBinder service) { 
      if (service instanceof TimerService.TimerBinder) { 
       mTimer = ((TimerService.TimerBinder) service).getTimer(); 
       openMenu(); 
      } 
      // No need to keep the service bound. 
      unbindService(this); 
     } 

     @Override 
     public void onServiceDisconnected(ComponentName name) { 
      // Nothing to do here. 
     } 
    }; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     mFromLiveCardVoice = getIntent().getBooleanExtra(LiveCard.EXTRA_FROM_LIVECARD_VOICE, false); 
     if (mFromLiveCardVoice) { 
      // When activated by voice from a live card, enable voice commands. The menu 
      // will automatically "jump" ahead to the items (skipping the guard phrase 
      // that was already said at the live card). 
      getWindow().requestFeature(WindowUtils.FEATURE_VOICE_COMMANDS); 
     } 

     // Bind to the Timer service to retrive the current timer's data. 
     Intent serviceIntent = new Intent(this, TimerService.class); 
     serviceIntent.putExtra(
      TimerService.EXTRA_TIMER_HASH_CODE, 
      getIntent().getIntExtra(TimerService.EXTRA_TIMER_HASH_CODE, 0)); 
     serviceIntent.setData(getIntent().getData()); 
     bindService(serviceIntent, mConnection, 0); 
    } 

    @Override 
    public void onAttachedToWindow() { 
     super.onAttachedToWindow(); 
     mAttachedToWindow = true; 
     openMenu(); 
    } 

    @Override 
    public void onDetachedFromWindow() { 
     super.onDetachedFromWindow(); 
     mAttachedToWindow = false; 
    } 

    @Override 
    public boolean onCreatePanelMenu(int featureId, Menu menu) { 
     if (isMyMenu(featureId)) { 
      getMenuInflater().inflate(R.menu.timer, menu); 
      return true; 
     } 
     return super.onCreatePanelMenu(featureId, menu); 
    } 

    @Override 
    public boolean onPreparePanel(int featureId, View view, Menu menu) { 
     mPreparePanelCalled = true; 
     if (isMyMenu(featureId)) { 
      if (mTimer == null) { 
       // Can't prepare the menu as we're not yet bound to a timer. 
       return false; 
      } else { 
       // Disable or enable menu item depending on the Timer's state. 

       // Don't reopen menu once we are finishing. This is necessary 
       // since voice menus reopen themselves while in focus. 
       return !mIsMenuClosed; 
      } 
     } 
     return super.onPreparePanel(featureId, view, menu); 
    } 

    @Override 
    public boolean onMenuItemSelected(int featureId, MenuItem item) { 
     if (!isMyMenu(featureId)) { 
      return super.onMenuItemSelected(featureId, item); 
     } 
     // Handle item selection. 
    } 

    @Override 
    public void onPanelClosed(int featureId, Menu menu) { 
     super.onPanelClosed(featureId, menu); 
     if (isMyMenu(featureId)) { 
      mIsMenuClosed = true; 
      if (!mIsSettingTimer) { 
       // Nothing else to do, closing the Activity. 
       finish(); 
      } 
     } 
    } 

    /** 
    * Opens the touch or voice menu iff all the conditions are satifisfied. 
    */ 
    private void openMenu() { 
     if (mAttachedToWindow && mTimer != null) { 
      if (mFromLiveCardVoice) { 
       if (mPreparePanelCalled) { 
        // Invalidates the previously prepared voice menu now that we can properly 
        // prepare it. 
        getWindow().invalidatePanelMenu(WindowUtils.FEATURE_VOICE_COMMANDS); 
       } 
      } else { 
       // Open the options menu for the touch flow. 
       openOptionsMenu(); 
      } 
     } 
    } 

    /** 
    * Returns {@code true} when the {@code featureId} belongs to the options menu or voice 
    * menu that are controlled by this menu activity. 
    */ 
    private boolean isMyMenu(int featureId) { 
     return featureId == Window.FEATURE_OPTIONS_PANEL || 
       featureId == WindowUtils.FEATURE_VOICE_COMMANDS; 
    } 
} 
+0

嗨阿蘭,THX的幫助。當服務類是我的設置中的主類時,使用綁定進行此設置是否也可以工作?這似乎發生在一個班,這使得它更容易一些。或者我錯過了某處的整體畫面。 :( – Jinxvar 2015-01-22 19:24:25

+0

不再需要,用你的答案解決了它,我在服務類上創建了一個活頁夾,並從活動中綁定它,從準備菜單時我稱之爲getter的活動中,getter檢查預測是否已經收到作品喜歡的魅力,thx了! – Jinxvar 2015-01-22 20:56:09