ChatGPTを少し触ってみた
最近流行りの「ChatGPT」を使ってコード分析をお願いしてみた。
対象のコードは
northpg.hatenablog.comの「MainActivity」のコードを貼り付けて解析してもらった。
解析の結果は
このコードは、Androidアプリ内でBluetoothをスキャンして、近くにあるBluetoothデバイスを探すサンプルアプリです。以下の機能を持ちます。
BluetoothAdapterオブジェクトを取得する。
Bluetoothデバイスのリストを表示する。
スキャン開始/停止ボタンを実装する。
Bluetoothデバイスの検出をブロードキャストレシーバーで処理する。
Bluetoothデバイスの探索が終了すると、BroadcastReceiverを解除する。
このコードでは、BluetoothAdapterクラスのインスタンスを作成し、Bluetoothの検出を行うためのBroadcastReceiverを登録しています。また、Bluetoothの検出を開始するためのUI機能も提供しています。
このコードでは、Bluetoothデバイスの探索に必要な位置情報権限が許可されているかどうかもチェックされています。許可されていない場合は、ユーザーに対して権限の許可を求めるダイアログを表示します。Bluetoothデバイスの探索が終了すると、BroadcastReceiverを解除します。
このコードは、Bluetoothをスキャンするための基本的な手順を示していますが、実際にアプリを開発する場合は、検出されたBluetoothデバイスとの通信を行う必要があります。また、Bluetoothデバイスがペアリングされるまで、通信を開始することはできません。
普通に優秀ですね、いろいろなことに使えそうなので引き続き触っていこうと思います。
【Android】SeekBarを使用して色(RGB)を変えてみる
お久しぶりです、今回はSeekBarを使用して、色を変化させるアプリを作ってみました。
開発環境&使用言語
- Android Studio 2021.1.1 Patch 3
- Java
RGB変更処理
まずは画面レイアウトから作成していきます
<?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:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0" android:orientation="vertical" android:paddingRight="0dp"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="RGBサンプル" /> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <Space android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" /> <TextView android:id="@+id/custom_color" android:layout_width="188dp" android:layout_height="161dp" android:layout_marginLeft="0dp" android:layout_marginRight="0dp" android:text="" /> <Space android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:weightSum="3"> <TextView android:layout_width="50dp" android:layout_height="wrap_content" android:layout_weight="0" android:text="赤(R)" /> <EditText android:id="@+id/Red_EditText" android:layout_width="100dp" android:layout_height="wrap_content" android:layout_weight="0" android:ems="0" android:imeOptions="actionDone" android:inputType="number" tools:text="0" /> <SeekBar android:id="@+id/Red_SeekBar" android:layout_width="150dp" android:layout_height="match_parent" android:layout_weight="0" android:max="255" android:min="0" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <TextView android:layout_width="50dp" android:layout_height="wrap_content" android:layout_weight="0" android:text="緑(G)" /> <EditText android:id="@+id/Green_EditText" android:layout_width="100dp" android:layout_height="wrap_content" android:ems="0" android:imeOptions="actionDone" android:inputType="number" tools:text="0" /> <SeekBar android:id="@+id/Green_SeekBar" android:layout_width="150dp" android:layout_height="match_parent" android:max="255" android:min="0" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <TextView android:layout_width="50dp" android:layout_height="wrap_content" android:layout_weight="0" android:text="青(B)" /> <EditText android:id="@+id/Blue_EditText" android:layout_width="100dp" android:layout_height="wrap_content" android:ems="0" android:imeOptions="actionDone" android:inputType="number" tools:text="0" /> <SeekBar android:id="@+id/Blue_SeekBar" android:layout_width="150dp" android:layout_height="match_parent" android:max="255" android:min="0" /> </LinearLayout> </LinearLayout> </LinearLayout>
次に処理を書いていきます
package com.example.rgbseekbarsampleapplication; import androidx.appcompat.app.AppCompatActivity; import android.graphics.Color; import android.os.Bundle; import android.view.KeyEvent; import android.view.inputmethod.EditorInfo; import android.widget.EditText; import android.widget.SeekBar; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private EditText Red_EditText; private EditText Green_EditText; private EditText Blue_EditText; private TextView custom_color; private SeekBar Red_SeekBar; private SeekBar Green_SeekBar; private SeekBar Blue_SeekBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Red_EditText = findViewById(R.id.Red_EditText); Green_EditText = findViewById(R.id.Green_EditText); Blue_EditText = findViewById(R.id.Blue_EditText); custom_color = findViewById(R.id.custom_color); Red_SeekBar = findViewById(R.id.Red_SeekBar); Green_SeekBar = findViewById(R.id.Green_SeekBar); Blue_SeekBar = findViewById(R.id.Blue_SeekBar); Red_EditText.setText("0"); Green_EditText.setText("0"); Blue_EditText.setText("0"); Red_SeekBar.setProgress(0); Green_SeekBar.setProgress(0); Blue_SeekBar.setProgress(0); custom_color.setBackgroundColor(Color.rgb(Integer.valueOf(Red_EditText.getText().toString()), Integer.valueOf(Green_EditText.getText().toString()), Integer.valueOf(Blue_EditText.getText().toString()))); //数値直入力 Red_EditText.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if(actionId == EditorInfo.IME_ACTION_DONE)//Enterキー押下時 { try { //入力された値が空または255を超えていないか判定する if(Red_EditText.getText().toString().equals("")) { Red_EditText.setText("0"); } else if(Integer.valueOf(Red_EditText.getText().toString()) > 255) { Red_EditText.setText("255"); } }catch (NumberFormatException e) { Red_EditText.setText("255"); } //値を反映 int r = Integer.valueOf(Red_EditText.getText().toString()); int g = Integer.valueOf(Green_EditText.getText().toString()); int b = Integer.valueOf(Blue_EditText.getText().toString()); Red_SeekBar.setProgress(r);//入力された値をシークバーに反映させる custom_color.setBackgroundColor(Color.rgb(r,g,b));//色を変化させる } return false; } }); Green_EditText.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if(actionId == EditorInfo.IME_ACTION_DONE)//Enterキー押下時 { try { //入力された値が空または255を超えていないか判定する if(Green_EditText.getText().toString().equals("")) { Green_EditText.setText("0"); } else if(Integer.valueOf(Green_EditText.getText().toString()) > 255) { Green_EditText.setText("255"); } }catch (NumberFormatException e) { Green_EditText.setText("255"); } //値を反映 int r = Integer.valueOf(Red_EditText.getText().toString()); int g = Integer.valueOf(Green_EditText.getText().toString()); int b = Integer.valueOf(Blue_EditText.getText().toString()); Green_SeekBar.setProgress(g);//入力された値をシークバーに反映させる custom_color.setBackgroundColor(Color.rgb(r,g,b));//色を変化させる } return false; } }); Blue_EditText.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if(actionId == EditorInfo.IME_ACTION_DONE)//Enterキー押下時 { try { //入力された値が空または255を超えていないか判定する if(Blue_EditText.getText().toString().equals("")) { Blue_EditText.setText("0"); } else if(Integer.valueOf(Blue_EditText.getText().toString()) > 255) { Blue_EditText.setText("255"); } }catch (NumberFormatException e) { Blue_EditText.setText("255"); } //値を反映 int r = Integer.valueOf(Red_EditText.getText().toString()); int g = Integer.valueOf(Green_EditText.getText().toString()); int b = Integer.valueOf(Blue_EditText.getText().toString()); Blue_SeekBar.setProgress(b);//入力された値をシークバーに反映させる custom_color.setBackgroundColor(Color.rgb(r,g,b));//色を変化させる } return false; } }); //シークバータッチ時 Red_SeekBar.setOnSeekBarChangeListener( new SeekBar.OnSeekBarChangeListener() { public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { Red_EditText.setText(String.valueOf(Red_SeekBar.getProgress())); int r = Integer.valueOf(Red_EditText.getText().toString()); int g = Integer.valueOf(Green_EditText.getText().toString()); int b = Integer.valueOf(Blue_EditText.getText().toString()); custom_color.setBackgroundColor(Color.rgb(r,g,b)); } public void onStartTrackingTouch(SeekBar seekBar) { } public void onStopTrackingTouch(SeekBar seekBar) { } } ); Green_SeekBar.setOnSeekBarChangeListener( new SeekBar.OnSeekBarChangeListener() { public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { Green_EditText.setText(String.valueOf(Green_SeekBar.getProgress())); int r = Integer.valueOf(Red_EditText.getText().toString()); int g = Integer.valueOf(Green_EditText.getText().toString()); int b = Integer.valueOf(Blue_EditText.getText().toString()); custom_color.setBackgroundColor(Color.rgb(r,g,b)); } public void onStartTrackingTouch(SeekBar seekBar) { } public void onStopTrackingTouch(SeekBar seekBar) { } } ); Blue_SeekBar.setOnSeekBarChangeListener( new SeekBar.OnSeekBarChangeListener() { public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { Blue_EditText.setText(String.valueOf(Blue_SeekBar.getProgress())); int r = Integer.valueOf(Red_EditText.getText().toString()); int g = Integer.valueOf(Green_EditText.getText().toString()); int b = Integer.valueOf(Blue_EditText.getText().toString()); custom_color.setBackgroundColor(Color.rgb(r,g,b)); } public void onStartTrackingTouch(SeekBar seekBar) { } public void onStopTrackingTouch(SeekBar seekBar) { } } ); } }
実際の実行画面
下の画像のようにシークバーを動かすと画像の色が変わります
AndroidでBluetooth デバイスを検出してみる
開発環境
- Android Studio 2020.3.1
- Java
パーミッション設定
AndroidでBluetoothを使用するに当たり、AndroidManifest.xmlに以下の権限を追加。
<!-- Bluetoothの機能を使用するための権限の宣言 --> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <!-- Bluetoothデバイスを検出するための権限の宣言 --> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <!-- Bluetoothの機能を使用するための位置情報権限の宣言 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
Bluetoothデバイス検出処理
MainActivityのレイアウトファイル activity_main
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".Activity.MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:weightSum="5" android:orientation="horizontal"> <Space android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" /> <Button android:id="@+id/scan_start_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="スキャン開始" /> <Space android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" /> <Button android:id="@+id/scan_stop_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="スキャン停止" /> <Space android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" /> </LinearLayout> <ListView android:id="@+id/DeviceListView" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
ListViewで使用するレイアウトファイル listitem_bluetoothdevice
<!--スキャンしたBluetoothデバイスをListviewに表示するときのitemレイアウト--> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/itemview_devicename" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="24dp"/> <TextView android:id="@+id/itemview_deviceaddress" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="12dp"/> </LinearLayout>
ListViewへitem追加用クラス BluetoothDeviceListAdapter
package com.example.bluetoothsampleapplication.Common; import android.app.Activity; import android.bluetooth.BluetoothDevice; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import com.example.bluetoothsampleapplication.R; import java.util.ArrayList; public class BluetoothDeviceListAdapter extends BaseAdapter { private ArrayList<BluetoothDevice> mBluetoothDeviceList; private LayoutInflater mInflator; public BluetoothDeviceListAdapter( Activity activity ) { super(); mBluetoothDeviceList = new ArrayList<BluetoothDevice>(); mInflator = activity.getLayoutInflater(); } // リストへの追加 public void addDevice( BluetoothDevice device ) { if( !mBluetoothDeviceList.contains( device ) ) { // 加えられていなければ加える mBluetoothDeviceList.add( device ); notifyDataSetChanged(); // ListViewの更新 } } // リストのクリア public void clear() { mBluetoothDeviceList.clear(); notifyDataSetChanged(); // ListViewの更新 } @Override public int getCount() { return mBluetoothDeviceList.size(); } @Override public Object getItem(int i) { return mBluetoothDeviceList.get(i); } @Override public long getItemId(int i) { return i; } static class ViewHolder { TextView deviceName; TextView deviceAddress; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; // General ListView optimization code. if( null == convertView ) { //アイテム用レイアウトビューを取得 convertView = mInflator.inflate( R.layout.listitem_bluetoothdevice, parent, false ); viewHolder = new ViewHolder(); viewHolder.deviceAddress = (TextView)convertView.findViewById( R.id.itemview_deviceaddress ); viewHolder.deviceName = (TextView)convertView.findViewById( R.id.itemview_devicename ); convertView.setTag( viewHolder ); } else { viewHolder = (ViewHolder)convertView.getTag(); } BluetoothDevice device = mBluetoothDeviceList.get( position ); String deviceName = device.getName(); if( null != deviceName && 0 < deviceName.length() ) { viewHolder.deviceName.setText( deviceName ); } else { viewHolder.deviceName.setText( "Unknown device" ); } viewHolder.deviceAddress.setText( device.getAddress() ); return convertView; } }
MainActivity
package com.example.bluetoothsampleapplication.Activity; import static android.bluetooth.BluetoothAdapter.ACTION_DISCOVERY_FINISHED; import static android.bluetooth.BluetoothAdapter.ACTION_DISCOVERY_STARTED; import static android.bluetooth.BluetoothDevice.ACTION_FOUND; import static android.bluetooth.BluetoothDevice.ACTION_NAME_CHANGED; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import android.Manifest; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.ListView; import android.widget.Toast; import com.example.bluetoothsampleapplication.Common.BluetoothDeviceListAdapter; import com.example.bluetoothsampleapplication.R; public class MainActivity extends AppCompatActivity { private BluetoothAdapter mBluetoothAdapter;// BluetoothAdapterオブジェクト private BluetoothDeviceListAdapter mBluetoothDeviceListAdapter;// リストビューの内容 private boolean mScanning = false; // スキャン中かどうかのフラグ private Button scan_start_button;//スキャン開始ボタン private Button scan_stop_button;//スキャン停止ボタン // ブロードキャストレシーバー private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent ) { String action = intent.getAction(); BluetoothDevice device = intent.getParcelableExtra( BluetoothDevice.EXTRA_DEVICE ); switch (action) { case ACTION_DISCOVERY_STARTED: Log.d("MainActivity", "ACTION_DISCOVERY_STARTED"); break; case ACTION_FOUND://デバイスが見つかったら Log.d("MainActivity", "ACTION_FOUND"); mBluetoothDeviceListAdapter.addDevice( device ); break; case ACTION_NAME_CHANGED: Log.d("MainActivity", "ACTION_NAME_CHANGED"); break; case ACTION_DISCOVERY_FINISHED: scan_start_button.setEnabled(true);//ボタンを有効化 scan_stop_button.setEnabled(false);//ボタンを無効化 Log.d("MainActivity", "ACTION_DISCOVERY_FINISHED"); // デバイス検出が終了した場合は、BroadcastReceiver を解除 context.unregisterReceiver(mBroadcastReceiver); break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);//layout呼び出し // Bluetoothアダプタの取得 BluetoothManager bluetoothManager = (BluetoothManager)getSystemService( Context.BLUETOOTH_SERVICE ); mBluetoothAdapter = bluetoothManager.getAdapter(); if( null == mBluetoothAdapter ) { // Android端末がBluetoothをサポートしていない Toast.makeText( this, "Bluetooth is not supported.", Toast.LENGTH_SHORT ).show(); finish(); // アプリ終了宣言 return; } //Android端末のBluetooth機能の有効化要求 requestBluetoothFeature(); //権限有効化要求(位置情報権限要求) if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION,}, 1000); return; } //UI設定 scan_start_button = findViewById(R.id.scan_start_button); scan_start_button.setOnClickListener(this::onClick); scan_stop_button = findViewById(R.id.scan_stop_button); scan_stop_button.setOnClickListener(this::onClick); scan_stop_button.setEnabled(false);//ボタンを無効化 // リストビューの設定 mBluetoothDeviceListAdapter = new BluetoothDeviceListAdapter( this ); // アダプターの初期化 ListView listView = (ListView)findViewById( R.id.DeviceListView ); // リストビューの取得 listView.setAdapter( mBluetoothDeviceListAdapter ); // リストビューにビューアダプターをセット // イベントフィルター設定 & ブロードキャストレシーバーの登録 IntentFilter filter = new IntentFilter(); filter.addAction(ACTION_DISCOVERY_STARTED);//Bluetoothスキャン開始検出 filter.addAction(ACTION_FOUND);//Bluetoothデバイス検出 filter.addAction(ACTION_DISCOVERY_FINISHED);//Bluetoothスキャン終了検出 registerReceiver( mBroadcastReceiver, filter ); } // 初回表示時、および、ポーズからの復帰時 @Override protected void onResume() { super.onResume(); } // 別のアクティビティ(か別のアプリ)に移行したことで、バックグラウンドに追いやられた時 @Override protected void onPause() { super.onPause(); } //Android端末のBluetooth機能の有効化要求 private void requestBluetoothFeature() { //Android端末のBluetooth機能が有効になっている場合は何もしない if( mBluetoothAdapter.isEnabled() ) { return; } //デバイスのBluetooth機能が有効になっていないときは、有効化要求(ダイアログ表示) Intent enableBtIntent = new Intent( BluetoothAdapter.ACTION_REQUEST_ENABLE ); startActivity(enableBtIntent); } // スキャンの開始 private void startScan() { // リストビューの内容を空にする。 mBluetoothDeviceListAdapter.clear(); // スキャンの開始 mScanning = true; mBluetoothAdapter.startDiscovery(); // 約 12 秒間の問い合わせのスキャンが行われる Log.d("Bluetooth","スキャン開始"); // メニューの更新 invalidateOptionsMenu(); } // スキャンの停止 private void stopScan() { Log.d("Bluetooth","スキャン停止"); // スキャンの停止 mScanning = false; mBluetoothAdapter.cancelDiscovery(); } public void onClick(View v) { switch (v.getId()) { case R.id.scan_start_button: startScan(); scan_start_button.setEnabled(false);//ボタンを無効化 scan_stop_button.setEnabled(true);//ボタンを有効化 break; case R.id.scan_stop_button: stopScan(); scan_start_button.setEnabled(true);//ボタンを有効化 scan_stop_button.setEnabled(false);//ボタンを無効化 break; } } }