blob: a9a956abccad76ce0ad486e26e889c03e3b3ebe2 [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.car.radio;
import android.car.Car;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.KeyEvent;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager.widget.ViewPager;
import com.android.car.media.common.source.MediaSource;
import com.android.car.media.common.source.MediaSourceViewModel;
import com.android.car.radio.bands.ProgramType;
import com.android.car.radio.util.Log;
import com.android.car.ui.toolbar.MenuItem;
import com.android.car.ui.toolbar.TabLayout;
import com.android.car.ui.toolbar.Toolbar;
import java.util.Arrays;
import java.util.List;
/**
* The main activity for the radio app.
*/
public class RadioActivity extends FragmentActivity {
private static final String TAG = "BcRadioApp.activity";
/**
* Intent action for notifying that the radio state has changed.
*/
private static final String ACTION_RADIO_APP_STATE_CHANGE =
"android.intent.action.RADIO_APP_STATE_CHANGE";
/**
* Boolean Intent extra indicating if the radio is the currently in the foreground.
*/
private static final String EXTRA_RADIO_APP_FOREGROUND =
"android.intent.action.RADIO_APP_STATE";
private RadioController mRadioController;
private BandController mBandController = new BandController();
private Toolbar mToolbar;
private RadioPagerAdapter mRadioPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "Radio app main activity created");
setContentView(R.layout.radio_activity);
mRadioController = new RadioController(this);
mRadioController.getCurrentProgram().observe(this, info -> {
ProgramType programType = ProgramType.fromSelector(info.getSelector());
if (programType != null) {
mBandController.setType(programType);
updateMenuItems();
}
});
mRadioPagerAdapter =
new RadioPagerAdapter(this, getSupportFragmentManager(), mRadioController);
ViewPager viewPager = findViewById(R.id.viewpager);
viewPager.setAdapter(mRadioPagerAdapter);
mToolbar = requireViewById(R.id.toolbar);
mToolbar.registerOnTabSelectedListener(t ->
viewPager.setCurrentItem(mToolbar.getTabLayout().getTabPosition(t)));
updateMenuItems();
setupTabsWithViewPager(viewPager);
MediaSourceViewModel model = MediaSourceViewModel.get(getApplication());
model.getPrimaryMediaSource().observe(this, source -> {
if (source != null) {
// Always go through the trampoline activity to keep all the dispatching logic
// there.
startActivity(new Intent(Car.CAR_INTENT_ACTION_MEDIA_TEMPLATE));
}
});
}
@Override
protected void onStart() {
super.onStart();
mRadioController.start();
Intent broadcast = new Intent(ACTION_RADIO_APP_STATE_CHANGE);
broadcast.putExtra(EXTRA_RADIO_APP_FOREGROUND, true);
sendBroadcast(broadcast);
}
@Override
protected void onStop() {
super.onStop();
Intent broadcast = new Intent(ACTION_RADIO_APP_STATE_CHANGE);
broadcast.putExtra(EXTRA_RADIO_APP_FOREGROUND, false);
sendBroadcast(broadcast);
}
@Override
protected void onDestroy() {
super.onDestroy();
mRadioController.shutdown();
Log.d(TAG, "Radio app main activity destroyed");
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_MEDIA_STEP_FORWARD:
mRadioController.step(true);
return true;
case KeyEvent.KEYCODE_MEDIA_STEP_BACKWARD:
mRadioController.step(false);
return true;
default:
return super.onKeyDown(keyCode, event);
}
}
/**
* Set whether background scanning is supported, to know whether to show the browse tab or not.
*/
public void setProgramListSupported(boolean supported) {
if (supported && mRadioPagerAdapter.addBrowseTab()) {
updateTabs();
}
}
/**
* Sets supported program types.
*/
public void setSupportedProgramTypes(@NonNull List<ProgramType> supported) {
mBandController.setSupportedProgramTypes(supported);
}
private void setupTabsWithViewPager(ViewPager viewPager) {
viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
mToolbar.selectTab(position);
}
});
updateTabs();
}
private void updateMenuItems() {
ProgramType currentBand = mBandController.getCurrentBand();
MenuItem bandSelectorMenuItem = MenuItem.builder(this)
.setIcon(currentBand != null ? currentBand.getResourceId() : 0)
.setOnClickListener(i -> {
ProgramType programType = mBandController.switchToNext();
mRadioController.switchBand(programType);
})
.build();
Intent appSelectorIntent = MediaSource.getSourceSelectorIntent(this, false);
MenuItem appSelectorMenuItem = MenuItem.builder(this)
.setIcon(R.drawable.ic_app_switch)
.setOnClickListener(m -> startActivity(appSelectorIntent))
.build();
mToolbar.setMenuItems(Arrays.asList(bandSelectorMenuItem, appSelectorMenuItem));
}
private void updateTabs() {
mToolbar.clearAllTabs();
for (int i = 0; i < mRadioPagerAdapter.getCount(); i++) {
Drawable icon = mRadioPagerAdapter.getPageIcon(i);
CharSequence title = mRadioPagerAdapter.getPageTitle(i);
mToolbar.addTab(new TabLayout.Tab(icon, title));
}
}
}