Home | History | Annotate | Download | only in sample
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package android.car.cluster.sample;
     17 
     18 import static android.car.cluster.sample.SampleClusterServiceImpl.LOCAL_BINDING_ACTION;
     19 
     20 import android.car.cluster.sample.SampleClusterServiceImpl.Listener;
     21 import android.content.ComponentName;
     22 import android.content.Intent;
     23 import android.content.ServiceConnection;
     24 import android.os.Bundle;
     25 import android.os.IBinder;
     26 import android.util.Log;
     27 import android.util.SparseArray;
     28 import android.view.InputDevice;
     29 import android.view.KeyEvent;
     30 import android.view.View;
     31 import android.view.inputmethod.InputMethodManager;
     32 import android.widget.Button;
     33 
     34 import androidx.fragment.app.Fragment;
     35 import androidx.fragment.app.FragmentActivity;
     36 import androidx.fragment.app.FragmentManager;
     37 import androidx.fragment.app.FragmentPagerAdapter;
     38 import androidx.viewpager.widget.ViewPager;
     39 
     40 import java.lang.reflect.InvocationTargetException;
     41 import java.util.HashMap;
     42 
     43 public class MainClusterActivity extends FragmentActivity
     44         implements Listener {
     45     private static final String TAG = MainClusterActivity.class.getSimpleName();
     46 
     47     private ViewPager mPager;
     48 
     49     private SampleClusterServiceImpl mService;
     50 
     51     private HashMap<Button, Facet<?>> mButtonToFacet = new HashMap<>();
     52     private SparseArray<Facet<?>> mOrderToFacet = new SparseArray<>();
     53 
     54     private InputMethodManager mInputMethodManager;
     55 
     56     private final View.OnFocusChangeListener mFacetButtonFocusListener =
     57             new View.OnFocusChangeListener() {
     58         @Override
     59         public void onFocusChange(View v, boolean hasFocus) {
     60             if (hasFocus) {
     61                 mPager.setCurrentItem(mButtonToFacet.get(v).order);
     62             }
     63         }
     64     };
     65 
     66     @Override
     67     protected void onCreate(Bundle savedInstanceState) {
     68         super.onCreate(savedInstanceState);
     69         setContentView(R.layout.activity_main);
     70 
     71         mInputMethodManager = getSystemService(InputMethodManager.class);
     72 
     73         Intent intent = new Intent(this, SampleClusterServiceImpl.class);
     74         intent.setAction(LOCAL_BINDING_ACTION);
     75         bindService(intent,
     76                 new ServiceConnection() {
     77                     @Override
     78                     public void onServiceConnected(ComponentName name, IBinder service) {
     79                         Log.i(TAG, "onServiceConnected, name: " + name + ", service: " + service);
     80                         mService = ((SampleClusterServiceImpl.LocalBinder) service)
     81                                 .getService();
     82                         mService.registerListener(MainClusterActivity.this);
     83                     }
     84 
     85                     @Override
     86                     public void onServiceDisconnected(ComponentName name) {
     87                         Log.i(TAG, "onServiceDisconnected, name: " + name);
     88                         mService = null;
     89                     }
     90                 }, BIND_AUTO_CREATE);
     91 
     92         registerFacets(
     93                 new Facet<>(findViewById(R.id.btn_nav), 0, NavigationFragment.class),
     94                 new Facet<>(findViewById(R.id.btn_phone), 1, PhoneFragment.class),
     95                 new Facet<>(findViewById(R.id.btn_music), 2, MusicFragment.class),
     96                 new Facet<>(findViewById(R.id.btn_car_info), 3, CarInfoFragment.class));
     97 
     98         mPager = findViewById(R.id.pager);
     99         mPager.setAdapter(new ClusterPageAdapter(getSupportFragmentManager()));
    100         mOrderToFacet.get(0).button.requestFocus();
    101     }
    102 
    103     @Override
    104     protected void onDestroy() {
    105         super.onDestroy();
    106         if (mService != null) {
    107             mService.unregisterListener();
    108         }
    109     }
    110 
    111     @Override
    112     public void onKeyEvent(KeyEvent event) {
    113         Log.i(TAG, "onKeyEvent, event: " + event);
    114 
    115         // This is a hack. We use SOURCE_CLASS_POINTER here because this type of input is associated
    116         // with the display. otherwise this event will be ignored in ViewRootImpl because injecting
    117         // KeyEvent w/o activity being focused is useless.
    118         event.setSource(event.getSource() | InputDevice.SOURCE_CLASS_POINTER);
    119         mInputMethodManager.dispatchKeyEventFromInputMethod(getCurrentFocus(), event);
    120     }
    121 
    122 
    123     public class ClusterPageAdapter extends FragmentPagerAdapter {
    124         public ClusterPageAdapter(FragmentManager fm) {
    125             super(fm);
    126         }
    127 
    128         @Override
    129         public int getCount() {
    130             return mButtonToFacet.size();
    131         }
    132 
    133         @Override
    134         public Fragment getItem(int position) {
    135             return mOrderToFacet.get(position).getOrCreateFragment();
    136         }
    137     }
    138 
    139     private void registerFacets(Facet<?>... facets) {
    140         for (Facet<?> f : facets) {
    141             registerFacet(f);
    142         }
    143     }
    144 
    145     private <T> void registerFacet(Facet<T> facet) {
    146         mOrderToFacet.append(facet.order, facet);
    147         mButtonToFacet.put(facet.button, facet);
    148 
    149         facet.button.setOnFocusChangeListener(mFacetButtonFocusListener);
    150     }
    151 
    152     private static class Facet<T> {
    153         Button button;
    154         Class<T> clazz;
    155         int order;
    156 
    157         Facet(Button button, int order, Class<T> clazz) {
    158             this.button = button;
    159             this.order = order;
    160             this.clazz = clazz;
    161         }
    162 
    163         private Fragment mFragment;
    164 
    165         Fragment getOrCreateFragment() {
    166             if (mFragment == null) {
    167                 try {
    168                     mFragment = (Fragment) clazz.getConstructors()[0].newInstance();
    169                 } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
    170                     throw new RuntimeException(e);
    171                 }
    172             }
    173             return mFragment;
    174         }
    175     }
    176 
    177     SampleClusterServiceImpl getService() {
    178         return mService;
    179     }
    180 }
    181