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.Handler;
     26 import android.os.IBinder;
     27 import android.support.v4.app.Fragment;
     28 import android.support.v4.app.FragmentActivity;
     29 import android.support.v4.app.FragmentManager;
     30 import android.support.v4.app.FragmentPagerAdapter;
     31 import android.support.v4.view.ViewPager;
     32 import android.text.TextUtils;
     33 import android.util.Log;
     34 import android.util.SparseArray;
     35 import android.view.KeyEvent;
     36 import android.view.View;
     37 import android.widget.Button;
     38 import android.widget.TextView;
     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 Button mNavButton;
     48     private Button mPhoneButton;
     49     private Button mCarInfoButton;
     50     private Button mMusicButton;
     51     private TextView mTextOverlay;
     52     private ViewPager mPager;
     53 
     54     private SampleClusterServiceImpl mService;
     55 
     56     private final Handler mHandler = new Handler();
     57 
     58     private HashMap<Button, Facet<?>> mButtonToFacet = new HashMap<>();
     59     private SparseArray<Facet<?>> mOrderToFacet = new SparseArray<>();
     60 
     61     private final View.OnFocusChangeListener mFacetButtonFocusListener =
     62             new View.OnFocusChangeListener() {
     63         @Override
     64         public void onFocusChange(View v, boolean hasFocus) {
     65             if (hasFocus) {
     66                 mPager.setCurrentItem(mButtonToFacet.get(v).order);
     67             }
     68         }
     69     };
     70 
     71     @Override
     72     protected void onCreate(Bundle savedInstanceState) {
     73         super.onCreate(savedInstanceState);
     74         setContentView(R.layout.activity_main);
     75 
     76         Intent intent = new Intent(this, SampleClusterServiceImpl.class);
     77         intent.setAction(LOCAL_BINDING_ACTION);
     78         bindService(intent,
     79                 new ServiceConnection() {
     80                     @Override
     81                     public void onServiceConnected(ComponentName name, IBinder service) {
     82                         Log.i(TAG, "onServiceConnected, name: " + name + ", service: " + service);
     83                         mService = ((SampleClusterServiceImpl.LocalBinder) service)
     84                                 .getService();
     85                         mService.registerListener(MainClusterActivity.this);
     86                     }
     87 
     88                     @Override
     89                     public void onServiceDisconnected(ComponentName name) {
     90                         Log.i(TAG, "onServiceDisconnected, name: " + name);
     91                         mService = null;
     92                     }
     93                 }, BIND_AUTO_CREATE);
     94 
     95         mNavButton = findViewById(R.id.btn_nav);
     96         mPhoneButton = findViewById(R.id.btn_phone);
     97         mCarInfoButton = findViewById(R.id.btn_car_info);
     98         mMusicButton = findViewById(R.id.btn_music);
     99         mTextOverlay = findViewById(R.id.text_overlay);
    100 
    101         registerFacets(
    102                 new Facet<>(mNavButton, 0, NavigationFragment.class),
    103                 new Facet<>(mPhoneButton, 1, PhoneFragment.class),
    104                 new Facet<>(mMusicButton, 2, MusicFragment.class),
    105                 new Facet<>(mCarInfoButton, 3, CarInfoFragment.class));
    106 
    107         mPager = (ViewPager) findViewById(R.id.pager);
    108         mPager.setAdapter(new ClusterPageAdapter(getSupportFragmentManager()));
    109 
    110         mNavButton.requestFocus();
    111     }
    112 
    113     @Override
    114     protected void onDestroy() {
    115         super.onDestroy();
    116         if (mService != null) {
    117             mService.unregisterListener();
    118         }
    119     }
    120 
    121     @Override
    122     public void onShowToast(String text) {
    123         if (mTextOverlay.getVisibility() == View.VISIBLE) {
    124             if (!TextUtils.isEmpty(mTextOverlay.getText())) {
    125                 mTextOverlay.setText(mTextOverlay.getText() + "\n" + text);
    126             } else {
    127                 mTextOverlay.setText(text);
    128             }
    129         }
    130 
    131         mTextOverlay.setVisibility(View.VISIBLE);
    132 
    133         mHandler.removeCallbacksAndMessages(null);
    134         mHandler.postDelayed(() -> {
    135             mTextOverlay.setVisibility(View.GONE);
    136             mTextOverlay.setText("");
    137         }, 3000);
    138     }
    139 
    140     @Override
    141     public void onKeyEvent(KeyEvent event) {
    142         Log.i(TAG, "onKeyEvent, event: " + event);
    143         dispatchKeyEvent(event);  // TODO: dispatch event doesn't work for some reason.
    144 
    145         if (event.getAction() == KeyEvent.ACTION_DOWN) {
    146             if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_RIGHT) {
    147                 int nextItem = (mPager.getCurrentItem() + 1) % mButtonToFacet.size();
    148                 mOrderToFacet.get(nextItem).button.requestFocus();
    149             } else if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_LEFT) {
    150                 int nextItem = (mPager.getCurrentItem() - 1);
    151                 if (nextItem < 0) nextItem =  mButtonToFacet.size() - 1;
    152                 mOrderToFacet.get(nextItem).button.requestFocus();
    153             }
    154         }
    155     }
    156 
    157     @Override
    158     public boolean dispatchKeyEvent(KeyEvent event) {
    159         boolean consumed = super.dispatchKeyEvent(event);
    160         Log.i(TAG, "dispatchKeyEvent, event: " + event + ", consumed: " + consumed);
    161         return consumed;
    162     }
    163 
    164     public class ClusterPageAdapter extends FragmentPagerAdapter {
    165         public ClusterPageAdapter(FragmentManager fm) {
    166             super(fm);
    167         }
    168 
    169         @Override
    170         public int getCount() {
    171             return mButtonToFacet.size();
    172         }
    173 
    174         @Override
    175         public Fragment getItem(int position) {
    176             return mOrderToFacet.get(position).getOrCreateFragment();
    177         }
    178     }
    179 
    180     private void registerFacets(Facet<?>... facets) {
    181         for (Facet<?> f : facets) {
    182             registerFacet(f);
    183         }
    184     }
    185 
    186     private <T> void registerFacet(Facet<T> facet) {
    187         mOrderToFacet.append(facet.order, facet);
    188         mButtonToFacet.put(facet.button, facet);
    189 
    190         facet.button.setOnFocusChangeListener(mFacetButtonFocusListener);
    191     }
    192 
    193     private static class Facet<T> {
    194         Button button;
    195         Class<T> clazz;
    196         int order;
    197 
    198         Facet(Button button, int order, Class<T> clazz) {
    199             this.button = button;
    200             this.order = order;
    201             this.clazz = clazz;
    202         }
    203 
    204         private Fragment mFragment;
    205 
    206         Fragment getOrCreateFragment() {
    207             if (mFragment == null) {
    208                 try {
    209                     mFragment = (Fragment) clazz.getConstructors()[0].newInstance();
    210                 } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
    211                     throw new RuntimeException(e);
    212                 }
    213             }
    214             return mFragment;
    215         }
    216     }
    217 
    218     SampleClusterServiceImpl getService() {
    219         return mService;
    220     }
    221 }
    222