| /* |
| * Copyright (C) 2017 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 android.car.cluster.sample; |
| |
| import static android.car.cluster.sample.SampleClusterServiceImpl.LOCAL_BINDING_ACTION; |
| |
| import android.car.cluster.sample.SampleClusterServiceImpl.Listener; |
| import android.content.ComponentName; |
| import android.content.Intent; |
| import android.content.ServiceConnection; |
| import android.os.Bundle; |
| import android.os.IBinder; |
| import android.util.Log; |
| import android.util.SparseArray; |
| import android.view.InputDevice; |
| import android.view.KeyEvent; |
| import android.view.View; |
| import android.view.inputmethod.InputMethodManager; |
| import android.widget.Button; |
| |
| import androidx.fragment.app.Fragment; |
| import androidx.fragment.app.FragmentActivity; |
| import androidx.fragment.app.FragmentManager; |
| import androidx.fragment.app.FragmentPagerAdapter; |
| import androidx.viewpager.widget.ViewPager; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.HashMap; |
| |
| public class MainClusterActivity extends FragmentActivity |
| implements Listener { |
| private static final String TAG = MainClusterActivity.class.getSimpleName(); |
| |
| private ViewPager mPager; |
| |
| private SampleClusterServiceImpl mService; |
| |
| private HashMap<Button, Facet<?>> mButtonToFacet = new HashMap<>(); |
| private SparseArray<Facet<?>> mOrderToFacet = new SparseArray<>(); |
| |
| private InputMethodManager mInputMethodManager; |
| |
| private final View.OnFocusChangeListener mFacetButtonFocusListener = |
| new View.OnFocusChangeListener() { |
| @Override |
| public void onFocusChange(View v, boolean hasFocus) { |
| if (hasFocus) { |
| mPager.setCurrentItem(mButtonToFacet.get(v).order); |
| } |
| } |
| }; |
| |
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| setContentView(R.layout.activity_main); |
| |
| mInputMethodManager = getSystemService(InputMethodManager.class); |
| |
| Intent intent = new Intent(this, SampleClusterServiceImpl.class); |
| intent.setAction(LOCAL_BINDING_ACTION); |
| bindService(intent, |
| new ServiceConnection() { |
| @Override |
| public void onServiceConnected(ComponentName name, IBinder service) { |
| Log.i(TAG, "onServiceConnected, name: " + name + ", service: " + service); |
| mService = ((SampleClusterServiceImpl.LocalBinder) service) |
| .getService(); |
| mService.registerListener(MainClusterActivity.this); |
| } |
| |
| @Override |
| public void onServiceDisconnected(ComponentName name) { |
| Log.i(TAG, "onServiceDisconnected, name: " + name); |
| mService = null; |
| } |
| }, BIND_AUTO_CREATE); |
| |
| registerFacets( |
| new Facet<>(findViewById(R.id.btn_nav), 0, NavigationFragment.class), |
| new Facet<>(findViewById(R.id.btn_phone), 1, PhoneFragment.class), |
| new Facet<>(findViewById(R.id.btn_music), 2, MusicFragment.class), |
| new Facet<>(findViewById(R.id.btn_car_info), 3, CarInfoFragment.class)); |
| |
| mPager = findViewById(R.id.pager); |
| mPager.setAdapter(new ClusterPageAdapter(getSupportFragmentManager())); |
| mOrderToFacet.get(0).button.requestFocus(); |
| } |
| |
| @Override |
| protected void onDestroy() { |
| super.onDestroy(); |
| if (mService != null) { |
| mService.unregisterListener(); |
| } |
| } |
| |
| @Override |
| public void onKeyEvent(KeyEvent event) { |
| Log.i(TAG, "onKeyEvent, event: " + event); |
| |
| // This is a hack. We use SOURCE_CLASS_POINTER here because this type of input is associated |
| // with the display. otherwise this event will be ignored in ViewRootImpl because injecting |
| // KeyEvent w/o activity being focused is useless. |
| event.setSource(event.getSource() | InputDevice.SOURCE_CLASS_POINTER); |
| mInputMethodManager.dispatchKeyEventFromInputMethod(getCurrentFocus(), event); |
| } |
| |
| |
| public class ClusterPageAdapter extends FragmentPagerAdapter { |
| public ClusterPageAdapter(FragmentManager fm) { |
| super(fm); |
| } |
| |
| @Override |
| public int getCount() { |
| return mButtonToFacet.size(); |
| } |
| |
| @Override |
| public Fragment getItem(int position) { |
| return mOrderToFacet.get(position).getOrCreateFragment(); |
| } |
| } |
| |
| private void registerFacets(Facet<?>... facets) { |
| for (Facet<?> f : facets) { |
| registerFacet(f); |
| } |
| } |
| |
| private <T> void registerFacet(Facet<T> facet) { |
| mOrderToFacet.append(facet.order, facet); |
| mButtonToFacet.put(facet.button, facet); |
| |
| facet.button.setOnFocusChangeListener(mFacetButtonFocusListener); |
| } |
| |
| private static class Facet<T> { |
| Button button; |
| Class<T> clazz; |
| int order; |
| |
| Facet(Button button, int order, Class<T> clazz) { |
| this.button = button; |
| this.order = order; |
| this.clazz = clazz; |
| } |
| |
| private Fragment mFragment; |
| |
| Fragment getOrCreateFragment() { |
| if (mFragment == null) { |
| try { |
| mFragment = (Fragment) clazz.getConstructors()[0].newInstance(); |
| } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| return mFragment; |
| } |
| } |
| |
| SampleClusterServiceImpl getService() { |
| return mService; |
| } |
| } |