반응형
1. Code
1. VibrationFragment.java
public class VibrationFragment extends Fragment {
private static final String TAG = "VibrationFragment";
private int newVibrationIntensity;
private long[] timing = null;
static ArrayList<VibrationPatternVO> mVibrationPatternList;
VibrationPatternListAdapter mVibrationPatternListAdapter;
RecyclerView mRecyclerView;
Slider vibrationIntensitySlider;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView;
rootView = inflater.inflate(R.layout.fragment_vibration, container, false);
mVibrationPatternList = Config.sharedInstance().getVibrationPatternList(getContext());
Log.d(TAG, "@@@@ onCreateView: " + mVibrationPatternList);
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.vibrationPatternRecyclerView);
vibrationIntensitySlider = (Slider) rootView.findViewById(R.id.vibrationIntensitySlider);
mVibrationPatternListAdapter = new VibrationPatternListAdapter();
mVibrationPatternListAdapter.setVibrationPatternList(mVibrationPatternList);
mVibrationPatternListAdapter.setOnItemClickListener(new VibrationPatternListAdapter.OnItemClickListener() {
@Override
public void onItemClick(int pos) {
Log.d(TAG, "@@@@ onCreateView: pos : " + pos);
Config.sharedInstance().setVibrationCheckBox(getContext(), pos);
if (newVibrationIntensity != Config.sharedInstance().getVibrationIntensity(getContext())){
newVibrationIntensity = Config.sharedInstance().getVibrationIntensity(getContext());
}
vibrator(getContext(),mVibrationPatternList.get(pos).getTiming(),newVibrationIntensity);
mVibrationPatternListAdapter.notifyDataSetChanged();
}
});
mRecyclerView.setAdapter(mVibrationPatternListAdapter);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
int vibrationIntensity = Config.sharedInstance().getVibrationIntensity(getContext());
if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.O){vibrationIntensitySlider.setVisibility(View.GONE);}
if (vibrationIntensity == 125) {
vibrationIntensitySlider.setValue(50);
} else if (vibrationIntensity == 0) {
vibrationIntensitySlider.setValue(0);
} else if (vibrationIntensity == 25) {
vibrationIntensitySlider.setValue(10);
} else if (vibrationIntensity == 50) {
vibrationIntensitySlider.setValue(20);
} else if (vibrationIntensity == 75) {
vibrationIntensitySlider.setValue(30);
} else if (vibrationIntensity == 100) {
vibrationIntensitySlider.setValue(40);
} else if (vibrationIntensity == 150) {
vibrationIntensitySlider.setValue(60);
} else if (vibrationIntensity == 175) {
vibrationIntensitySlider.setValue(70);
} else if (vibrationIntensity == 200) {
vibrationIntensitySlider.setValue(80);
} else if (vibrationIntensity == 225) {
vibrationIntensitySlider.setValue(90);
} else if (vibrationIntensity == 250) {
vibrationIntensitySlider.setValue(100);
}
vibrationIntensitySlider.addOnChangeListener(new Slider.OnChangeListener() {
@SuppressLint("RestrictedApi")
@Override
public void onValueChange(@NonNull @NotNull Slider slider, float value, boolean fromUser) {
switch ((int) value) {
case 0:
newVibrationIntensity = 0;
break;
case 10:
newVibrationIntensity = 25;
break;
case 20:
newVibrationIntensity = 50;
break;
case 30:
newVibrationIntensity = 75;
break;
case 40:
newVibrationIntensity = 100;
break;
default:
case 50:
newVibrationIntensity = 125;
break;
case 60:
newVibrationIntensity = 150;
break;
case 70:
newVibrationIntensity = 175;
break;
case 80:
newVibrationIntensity = 200;
break;
case 90:
newVibrationIntensity = 225;
break;
case 100:
newVibrationIntensity = 250;
break;
}
Config.sharedInstance().setVibrationIntensity(getContext(), newVibrationIntensity);
timing = Config.sharedInstance().getVibrationPatternList(getContext()).get(Config.sharedInstance().getVibrationCheckBox(getContext())).getTiming();
vibrator(getContext(),timing, newVibrationIntensity);
}
});
final MaterialIconView btnClose = (MaterialIconView) rootView.findViewById(R.id.btnClose);
btnClose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
MainActivity.Event mEvent = new MainActivity.Event(MainActivity.DISMISS_SECOND_FRAGMENT);
mEvent.param1 = VibrationFragment.this;
EventBus.getDefault().post(mEvent);
}
});
return rootView;
}
//진동
public void vibrator(Context context, long[] mTiming, int plusAmplitudes){
long[] timing = new long[]{0,100,50,100,500,100}; //ms 타이밍
int[] amplitudes = new int[]{0,125,0,125,0,125};
if(plusAmplitudes >= 0){
amplitudes = new int[]{0,0+plusAmplitudes,0,0+plusAmplitudes,0,0+plusAmplitudes}; //진동세기
}
if(mTiming != null) { //기본값이 없으면 UC 패턴
timing = mTiming;
}
Vibrator vibrator = (Vibrator) context.getSystemService(context.VIBRATOR_SERVICE);
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ALARM)
.build();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && Build.VERSION_CODES.R >= Build.VERSION.SDK_INT) {
vibrator.vibrate(VibrationEffect.createWaveform(timing, amplitudes,-1), audioAttributes);
} else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O){
vibrator.vibrate(timing,-1, audioAttributes);
} else {
vibrator.vibrate(VibrationEffect.createWaveform(timing, amplitudes, -1), audioAttributes);
}
}
}
2. VibrationPatternListAdapter.java
public class VibrationPatternListAdapter extends RecyclerView.Adapter<VibrationPatternListAdapter.ViewHolder> {
//OnClickListener Custom
public interface OnItemClickListener{
void onItemClick(int pos);
}
private OnItemClickListener onItemClickListener = null;
public void setOnItemClickListener(OnItemClickListener listener) {
this.onItemClickListener = listener;
}
private ArrayList<VibrationPatternVO> mVibrationPatternList;
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.vibration_pattern_list_item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.onBind(mVibrationPatternList.get(position));
}
public void setVibrationPatternList(ArrayList<VibrationPatternVO> list){
this.mVibrationPatternList = list;
notifyDataSetChanged();
}
@Override
public int getItemCount() {
return mVibrationPatternList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView name;
CheckBox checkBox;
LinearLayout itemLayout;
public ViewHolder(@NonNull View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.text1);
checkBox = (CheckBox) itemView.findViewById(R.id.checkBox);
itemLayout = (LinearLayout) itemView.findViewById(R.id.itemLayout);
itemLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
if(onItemClickListener != null){
onItemClickListener.onItemClick(position);
}
}
}
});
}
void onBind(VibrationPatternVO item){
name.setText(item.getName());
if(getAdapterPosition() == (Config.sharedInstance().getVibrationCheckBox(checkBox.getContext()))) {
checkBox.setChecked(true);
} else{
checkBox.setChecked(false);
}
}
}
}
3. fragment_vibration.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/default_background"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/titleLayout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/default_background"
android:gravity="center_vertical"
android:orientation="horizontal">
<net.steamcrafted.materialiconlib.MaterialIconView
android:id="@+id/btnClose"
android:layout_width="50dp"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:background="@android:color/transparent"
android:scaleType="center"
app:materialIcon="arrow_left"
app:materialIconColor="@color/md_black_1000"
app:materialIconSize="24dp" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/btnClose"
android:layout_weight="1"
android:gravity="center_horizontal"
android:text="@string/vibration_title"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/md_black_1000"
android:textSize="17dp"
android:textStyle="bold" />
</RelativeLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">
<androidx.cardview.widget.CardView
android:id="@+id/cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginVertical="20dp"
android:background="@color/white"
app:cardCornerRadius="10dp"
app:cardElevation="3dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/vibrationPatternRecyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
</RelativeLayout>
</androidx.cardview.widget.CardView>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginHorizontal="20dp"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/smallText"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:gravity="center"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.5">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/vibration_weak"
android:textColor="@color/md_black_1000"
android:textSize="9sp" />
</LinearLayout>
<com.google.android.material.slider.Slider
android:id="@+id/vibrationIntensitySlider"
android:layout_width="0dp"
android:layout_height="50dp"
android:stepSize="10.0"
android:layout_marginHorizontal="10dp"
android:theme="@style/CustomPhotoPickerTheme"
android:valueFrom="0.0"
android:valueTo="100.0"
app:haloColor="@color/colorPrimary"
app:labelBehavior="gone"
app:tickColor="@color/colorPrimary"
app:trackColorActive="@color/md_grey_300"
app:trackColorInactive="@color/md_grey_300"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@+id/smallText"
app:layout_constraintRight_toLeftOf="@+id/largeText"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.5"/>
<LinearLayout
android:id="@+id/largeText"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:gravity="center"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.5">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/vibration_strong"
android:textColor="@color/md_black_1000"
android:textSize="21sp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
4. vibration_pattern_list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/itemLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/ripple_round_gray"
android:clickable="true"
android:padding="5dp"
android:orientation="horizontal"
tools:ignore="MissingDefaultResource">
<TextView
android:layout_marginStart="5dp"
android:id="@+id/text1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/checkBox"
android:textColor="@color/md_grey_900"
android:textSize="15dp" />
<CheckBox
android:id="@+id/checkBox"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:background="@drawable/custom_checkbox"
android:button="@null"
android:clickable="false" />
</LinearLayout>
5. VibrationPatternVO.java
public class VibrationPatternVO {
String name;
long[] timing;
public VibrationPatternVO(String name, long[] timing){
this.name = name;
this.timing = timing;
}
public void setName(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setTiming(long[] timing){
this.timing = timing;
}
public long[] getTiming() {
return timing;
}
6. Config.java
public class Config {
public ArrayList<VibrationPatternVO> vibrationPatternList;
private static final Config config = new Config();
public static Config sharedInstance() {
return config;
}
public void initialize(Context context) { //로그인 시 실행
initVibrationPatternList(context); //진동패턴 초기화
}
public ArrayList<VibrationPatternVO> getVibrationPatternList(Context context) { //진동패턴
if(vibrationPatternList != null && vibrationPatternList.size() == 0){
vibrationPatternList.add(new VibrationPatternVO(context.getString(R.string.vibration_pattern_basic),new long[]{0,100,50,100,500,100}));
vibrationPatternList.add(new VibrationPatternVO(context.getString(R.string.vibration_pattern_1),new long[]{0,50,0,0,0,0}));
vibrationPatternList.add(new VibrationPatternVO(context.getString(R.string.vibration_pattern_2),new long[]{0,50,30,50,0,0}));
vibrationPatternList.add(new VibrationPatternVO(context.getString(R.string.vibration_pattern_3),new long[]{0,500,50,500,0,0}));
vibrationPatternList.add(new VibrationPatternVO(context.getString(R.string.vibration_pattern_4),new long[]{0,200,30,50,30,200}));
vibrationPatternList.add(new VibrationPatternVO(context.getString(R.string.vibration_pattern_5),new long[]{0,500,30,500,30,500}));
}
return vibrationPatternList;
}
public void initVibrationPatternList(Context context) { //진동패턴 초기화
if(vibrationPatternList == null){
vibrationPatternList = new ArrayList<>();
vibrationPatternList.add(new VibrationPatternVO(context.getString(R.string.vibration_pattern_basic),new long[]{0,100,50,100,500,100}));
vibrationPatternList.add(new VibrationPatternVO(context.getString(R.string.vibration_pattern_1),new long[]{0,50,0,0,0,0}));
vibrationPatternList.add(new VibrationPatternVO(context.getString(R.string.vibration_pattern_2),new long[]{0,50,30,50,0,0}));
vibrationPatternList.add(new VibrationPatternVO(context.getString(R.string.vibration_pattern_3),new long[]{0,500,50,500,0,0}));
vibrationPatternList.add(new VibrationPatternVO(context.getString(R.string.vibration_pattern_4),new long[]{0,200,30,50,30,200}));
vibrationPatternList.add(new VibrationPatternVO(context.getString(R.string.vibration_pattern_5),new long[]{0,500,30,500,30,500}));
}
}
// 진동세기 가져오기
public Integer getVibrationIntensity(Context context) {
SharedPreferences ucaPreferences = context.getSharedPreferences(UCAConstants.UCA_APP_NAME, Activity.MODE_PRIVATE);
return ucaPreferences.getInt(UCAConstants.SAVE_VIBRATION_INTENSITY, 125);
}
// 진동세기 저장
public void setVibrationIntensity(Context context, Integer value) {
SharedPreferences ucaPreferences = context.getSharedPreferences(UCAConstants.UCA_APP_NAME, Activity.MODE_PRIVATE);
SharedPreferences.Editor edit = ucaPreferences.edit();
edit.putInt(UCAConstants.SAVE_VIBRATION_INTENSITY, value);
edit.apply();
}
// 진동패턴 포지션 가져오기
public Integer getVibrationCheckBox(Context context) {
SharedPreferences ucaPreferences = context.getSharedPreferences(UCAConstants.UCA_APP_NAME, Activity.MODE_PRIVATE);
return ucaPreferences.getInt(UCAConstants.SAVE_VIBRATION_PATTERN_CHECKBOX, 0);
}
// 진동패턴 포지션 저장
public void setVibrationCheckBox(Context context, Integer value) {
SharedPreferences ucaPreferences = context.getSharedPreferences(UCAConstants.UCA_APP_NAME, Activity.MODE_PRIVATE);
SharedPreferences.Editor edit = ucaPreferences.edit();
edit.putInt(UCAConstants.SAVE_VIBRATION_PATTERN_CHECKBOX, value);
edit.apply();
}
}
7. UCAConstants.java
// 진동 세기 저장
public static final String SAVE_VIBRATION_INTENSITY = "SAVE_VIBRATION_INTENSITY";
// 진동 패턴 체크박스 포지션 저장
public static final String SAVE_VIBRATION_PATTERN_CHECKBOX = "SAVE_VIBRATION_PATTERN_CHECKBOX";
2. 사용법
1. Permission
<uses-permission android:name = "android.permission.VIBRATE"/>
2. Code
Vibrator vibrator = (Vibrator) context.getSystemService(context.VIBRATOR_SERVICE);
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ALARM)
.build();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && Build.VERSION_CODES.R >= Build.VERSION.SDK_INT) {
vibrator.vibrate(VibrationEffect.createWaveform(timing, amplitudes,-1), audioAttributes);
} else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O){
vibrator.vibrate(timing,-1, audioAttributes);
} else {
vibrator.vibrate(VibrationEffect.createWaveform(timing, amplitudes, -1), audioAttributes);
}
1. 반복횟수 -1은 1번, 0은 무한반복
2. timing
timing은 진동 패턴이다
long[] timing = new long[]{0,100,50,100,500,100}; //ms 타이밍
ms단위의 시간으로 진동의 길이와 끊어주는 시간을 만들 수 있다.
3. AudioAttributes
설정을 해주지 않으면 백그라운드에서 동작하지 않는다.
4. amplitudes
amplitudes는 진동세기이다
int[] amplitudes = new int[]{0,125,0,125,0,125};
기본적으로 처음 진동세기는 지정해주어도 동작하지 않는다
0으로 시작하는 것이 좋다
5. Version
버전별로 진동의 기능지원이 다르다.
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && Build.VERSION_CODES.R >= Build.VERSION.SDK_INT
Build.VERSION.SDK_INT <= Build.VERSION_CODES.O
"O버전 <= 지금버전 <= R버전"의 경우
VibrationEffect가 도입되었다.
기본 : VibrationEffect.createWaveform(timing, amplitudes,-1)
똑같이 timing는 패턴, amplitudes는 진동세기, -1는 반복횟수(1번)/0은 무한반복
"지금버전 <= O버전
vibrate를 가지고 바로 구현하면 된다
그외(R버전보다 클 때)
VibrationEffect 사용하면 된다
6. 채널생성
Reference
https://lakue.tistory.com/58
https://codechacha.com/ko/android-vibration/
반응형
'Android > Android Java' 카테고리의 다른 글
[Android Java] Notification Channel (0) | 2023.10.27 |
---|---|
[Android Java] 오디오모드(벨모드,진동모드,무음모드) (0) | 2023.10.27 |
[Android Java] 애니메이션 만들기 (0) | 2023.10.27 |
[Android Java] 화면 회전시 새로 띄우기 (0) | 2023.10.27 |
[Android Java] configChanges 설정 (1) | 2023.10.27 |