1 /* 2 * Copyright 2022 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 17 package com.example.androidx.mediarouting.activities; 18 19 import static com.example.androidx.mediarouting.ui.UiUtils.setUpEnumBasedSpinner; 20 21 import android.content.ComponentName; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.ServiceConnection; 25 import android.os.Bundle; 26 import android.os.IBinder; 27 import android.text.Editable; 28 import android.text.TextWatcher; 29 import android.widget.Button; 30 import android.widget.EditText; 31 import android.widget.Switch; 32 33 import androidx.appcompat.app.AppCompatActivity; 34 import androidx.core.util.Consumer; 35 36 import com.example.androidx.mediarouting.R; 37 import com.example.androidx.mediarouting.RoutesManager; 38 import com.example.androidx.mediarouting.data.RouteItem; 39 import com.example.androidx.mediarouting.services.SampleDynamicGroupMediaRouteProviderService; 40 41 import org.jspecify.annotations.NonNull; 42 import org.jspecify.annotations.Nullable; 43 44 /** Allows the user to add and edit routes. */ 45 public class AddEditRouteActivity extends AppCompatActivity { 46 private static final String EXTRA_ROUTE_ID_KEY = "routeId"; 47 48 private @Nullable SampleDynamicGroupMediaRouteProviderService mService; 49 private ServiceConnection mConnection; 50 private RoutesManager mRoutesManager; 51 private RouteItem mRouteItem; 52 53 /** Launches the activity. */ launchActivity(@onNull Context context, @Nullable String routeId)54 public static void launchActivity(@NonNull Context context, @Nullable String routeId) { 55 Intent intent = new Intent(context, AddEditRouteActivity.class); 56 intent.putExtra(EXTRA_ROUTE_ID_KEY, routeId); 57 context.startActivity(intent); 58 } 59 60 @Override onCreate(@ullable Bundle savedInstanceState)61 protected void onCreate(@Nullable Bundle savedInstanceState) { 62 super.onCreate(savedInstanceState); 63 setContentView(R.layout.activity_add_edit_route); 64 65 mRoutesManager = RoutesManager.getInstance(getApplicationContext()); 66 67 String routeId = getIntent().getStringExtra(EXTRA_ROUTE_ID_KEY); 68 mRouteItem = mRoutesManager.getRouteWithId(routeId); 69 mConnection = new ProviderServiceConnection(); 70 71 if (mRouteItem == null) { 72 mRouteItem = new RouteItem(); 73 } else { 74 mRouteItem = RouteItem.copyOf(mRouteItem); 75 } 76 77 setUpViews(); 78 } 79 80 @Override onStart()81 protected void onStart() { 82 super.onStart(); 83 Intent intent = new Intent(this, SampleDynamicGroupMediaRouteProviderService.class); 84 intent.setAction(SampleDynamicGroupMediaRouteProviderService.ACTION_BIND_LOCAL); 85 bindService(intent, mConnection, Context.BIND_AUTO_CREATE); 86 } 87 88 @Override onStop()89 protected void onStop() { 90 super.onStop(); 91 unbindService(mConnection); 92 } 93 setUpViews()94 private void setUpViews() { 95 setUpEditText( 96 findViewById(R.id.name_edit_text), 97 mRouteItem.getName(), 98 newName -> mRouteItem.setName(newName)); 99 100 setUpEditText( 101 findViewById(R.id.description_edit_text), 102 mRouteItem.getDescription(), 103 newDescription -> mRouteItem.setDescription(newDescription)); 104 105 setUpEnumBasedSpinner( 106 /* context= */ this, 107 findViewById(R.id.control_filters_spinner), 108 mRouteItem.getControlFilter(), 109 newControlFilter -> 110 mRouteItem.setControlFilter((RouteItem.ControlFilter) newControlFilter)); 111 112 setUpEnumBasedSpinner( 113 /* context= */ this, 114 findViewById(R.id.playback_stream_spinner), 115 mRouteItem.getPlaybackStream(), 116 newPlaybackStream -> 117 mRouteItem.setPlaybackStream((RouteItem.PlaybackStream) newPlaybackStream)); 118 119 setUpEnumBasedSpinner( 120 /* context= */ this, 121 findViewById(R.id.playback_type_spinner), 122 mRouteItem.getPlaybackType(), 123 newPlaybackType -> 124 mRouteItem.setPlaybackType((RouteItem.PlaybackType) newPlaybackType)); 125 126 setUpEnumBasedSpinner( 127 /* context= */ this, 128 findViewById(R.id.device_type_spinner), 129 mRouteItem.getDeviceType(), 130 newDeviceType -> mRouteItem.setDeviceType((RouteItem.DeviceType) newDeviceType)); 131 132 setUpEnumBasedSpinner( 133 /* context= */ this, 134 findViewById(R.id.volume_handling_spinner), 135 mRouteItem.getVolumeHandling(), 136 mewVolumeHandling -> 137 mRouteItem.setVolumeHandling((RouteItem.VolumeHandling) mewVolumeHandling)); 138 139 setUpEditText( 140 findViewById(R.id.volume_edit_text), 141 String.valueOf(mRouteItem.getVolume()), 142 mewVolume -> mRouteItem.setVolume(Integer.parseInt(mewVolume))); 143 144 setUpEditText( 145 findViewById(R.id.volume_max_edit_text), 146 String.valueOf(mRouteItem.getVolumeMax()), 147 mewVolumeMax -> mRouteItem.setVolumeMax(Integer.parseInt(mewVolumeMax))); 148 149 setUpSwitch( 150 findViewById(R.id.can_disconnect_switch), 151 mRouteItem.isCanDisconnect(), 152 newValue -> mRouteItem.setCanDisconnect(newValue)); 153 154 setUpSwitch( 155 findViewById(R.id.is_sender_driven_switch), 156 mRouteItem.isSenderDriven(), 157 newValue -> mRouteItem.setSenderDriven(newValue)); 158 159 setUpSaveButton(); 160 } 161 setUpSaveButton()162 private void setUpSaveButton() { 163 Button saveButton = findViewById(R.id.save_button); 164 saveButton.setOnClickListener( 165 view -> { 166 mRoutesManager.addRoute(mRouteItem); 167 if (mService != null) { 168 mService.reloadRoutes(); 169 } 170 finish(); 171 }); 172 } 173 setUpSwitch(Switch switchWidget, boolean currentValue, Consumer<Boolean> propertySetter)174 private static void setUpSwitch(Switch switchWidget, boolean currentValue, 175 Consumer<Boolean> propertySetter) { 176 switchWidget.setChecked(currentValue); 177 switchWidget.setOnCheckedChangeListener((compoundButton, b) -> propertySetter.accept(b)); 178 } 179 setUpEditText( EditText editText, String currentValue, Consumer<String> propertySetter)180 private static void setUpEditText( 181 EditText editText, String currentValue, Consumer<String> propertySetter) { 182 editText.setText(currentValue); 183 editText.addTextChangedListener( 184 new TextWatcher() { 185 @Override 186 public void beforeTextChanged( 187 CharSequence charSequence, int i, int i1, int i2) {} 188 189 @Override 190 public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { 191 propertySetter.accept(charSequence.toString()); 192 } 193 194 @Override 195 public void afterTextChanged(Editable editable) {} 196 }); 197 } 198 199 private class ProviderServiceConnection implements ServiceConnection { 200 201 @Override onServiceConnected(ComponentName className, IBinder service)202 public void onServiceConnected(ComponentName className, IBinder service) { 203 SampleDynamicGroupMediaRouteProviderService.LocalBinder binder = 204 (SampleDynamicGroupMediaRouteProviderService.LocalBinder) service; 205 mService = binder.getService(); 206 } 207 208 @Override onServiceDisconnected(ComponentName unusedComponentName)209 public void onServiceDisconnected(ComponentName unusedComponentName) { 210 mService = null; 211 } 212 } 213 } 214