欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android在類微信程序中實(shí)現(xiàn)藍(lán)牙聊天功能的示例代碼

 更新時(shí)間:2020年06月04日 09:25:07   作者:ttt湯圓  
這篇文章主要介紹了Android在類微信程序中實(shí)現(xiàn)藍(lán)牙聊天功能,本文通過實(shí)例代碼給大家介紹的非常想詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

項(xiàng)目要求

1.初次打開程序時(shí)右上角標(biāo)題欄顯示“無連接”,點(diǎn)擊旁邊的按鈕選擇“我的好友”,進(jìn)入配對(duì)界面;
2.選擇好友之后,返回主界面,標(biāo)題欄會(huì)顯示已連接的手機(jī)型號(hào);
3.兩部手機(jī)間可通過藍(lán)牙聊天

效果展示

在這里插入圖片描述
在這里插入圖片描述

項(xiàng)目結(jié)構(gòu)

在這里插入圖片描述

主要代碼

1.在清單文件中注冊(cè)權(quán)限

<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />

2.在文件res / values / strings.xml里,添加程序運(yùn)行過程中的狀態(tài)描述文本及配色代碼等

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <string name="app_name">藍(lán)牙Demo</string> 
 <string name="send">發(fā)送</string>
 <string name="not_connected">你沒有鏈接一個(gè)設(shè)備</string>
 <string name="bt_not_enabled_leaving">藍(lán)牙不可用,離開聊天室</string>
 <string name="title_connecting">鏈接中...</string>
 <string name="title_connected_to">連接到:</string>
 <string name="title_not_connected">無鏈接</string> 
 <string name="scanning">藍(lán)牙設(shè)備搜索中...</string>
 <string name="select_device">選擇一個(gè)好友鏈接</string>
 <string name="none_paired">沒有配對(duì)好友</string>
 <string name="none_found">附近沒有發(fā)現(xiàn)好友</string>
 <string name="title_paired_devices">已配對(duì)好友</string>
 <string name="title_other_devices">其它可連接好友</string>
 <string name="button_scan">搜索好友</string>
 <string name="connect">我的好友</string>
 <string name="discoverable">設(shè)置在線</string>
 <string name="back">退出</string>
 <string name="startVideo">開始聊天</string>
 <string name="stopVideo">結(jié)束聊天</string> 
</resources>

用于藍(lán)牙會(huì)話的服務(wù)組件ChatService.java中有三個(gè)內(nèi)部類:AcceptThread(接受新連接)、ConnectThread(發(fā)出連接)和ConnectedThread (已連接)。

// 創(chuàng)建監(jiān)聽線程,準(zhǔn)備接受新連接。使用阻塞方式,調(diào)用 BluetoothServerSocket.accept()
 private class AcceptThread extends Thread {
  private final BluetoothServerSocket mmServerSocket;

  public AcceptThread() {
   BluetoothServerSocket tmp = null;
   try {
    //使用射頻端口(RF comm)監(jiān)聽
    tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
   } catch (IOException e) {
   }
   mmServerSocket = tmp;
  }

  @Override
  public void run() {
   setName("AcceptThread");
   BluetoothSocket socket = null;
   while (mState != STATE_CONNECTED) {
    try {
     socket = mmServerSocket.accept();
    } catch (IOException e) {
     break;
    }
    if (socket != null) {
     synchronized (ChatService.this) {
      switch (mState) {
       case STATE_LISTEN:
       case STATE_CONNECTING:
        connected(socket, socket.getRemoteDevice());
        break;
       case STATE_NONE:
       case STATE_CONNECTED:
        try {
         socket.close();
        } catch (IOException e) {
         e.printStackTrace();
        }
        break;
      }
     }
    }
   }
  }

  public void cancel() {
   try {
    mmServerSocket.close();
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
 }

 /*
  連接線程,專門用來對(duì)外發(fā)出連接對(duì)方藍(lán)牙的請(qǐng)求和處理流程。
  構(gòu)造函數(shù)里通過 BluetoothDevice.createRfcommSocketToServiceRecord() ,
  從待連接的 device 產(chǎn)生 BluetoothSocket. 然后在 run 方法中 connect ,
  成功后調(diào)用 BluetoothChatSevice 的 connected() 方法。定義 cancel() 在關(guān)閉線程時(shí)能夠關(guān)閉相關(guān)socket 。
  */
 private class ConnectThread extends Thread {
  private final BluetoothSocket mmSocket;
  private final BluetoothDevice mmDevice;

  public ConnectThread(BluetoothDevice device) {
   mmDevice = device;
   BluetoothSocket tmp = null;
   try {
    tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
   } catch (IOException e) {
    e.printStackTrace();
   }
   mmSocket = tmp;
  }

  @Override
  public void run() {
   setName("ConnectThread");
   mAdapter.cancelDiscovery();
   try {
    mmSocket.connect();
   } catch (IOException e) {
    connectionFailed();
    try {
     mmSocket.close();
    } catch (IOException e2) {
     e.printStackTrace();
    }
    ChatService.this.start();
    return;
   }
   synchronized (ChatService.this) {
    mConnectThread = null;
   }
   connected(mmSocket, mmDevice);
  }

  public void cancel() {
   try {
    mmSocket.close();
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
 }

 /*
  雙方藍(lán)牙連接后一直運(yùn)行的線程;構(gòu)造函數(shù)中設(shè)置輸入輸出流。
  run()方法中使用阻塞模式的 InputStream.read()循環(huán)讀取輸入流,然后發(fā)送到 UI 線程中更新聊天消息。
  本線程也提供了 write() 將聊天消息寫入輸出流傳輸至對(duì)方,傳輸成功后回寫入 UI 線程。最后使用cancel()關(guān)閉連接的 socket
  */
 private class ConnectedThread extends Thread {
  private final BluetoothSocket mmSocket;
  private final InputStream mmInStream;
  private final OutputStream mmOutStream;

  public ConnectedThread(BluetoothSocket socket) {
   mmSocket = socket;
   InputStream tmpIn = null;
   OutputStream tmpOut = null;
   try {
    tmpIn = socket.getInputStream();
    tmpOut = socket.getOutputStream();
   } catch (IOException e) {
    e.printStackTrace();
   }
   mmInStream = tmpIn;
   mmOutStream = tmpOut;
  }

  @Override
  public void run() {
   byte[] buffer = new byte[1024];
   int bytes;
   while (true) {
    try {
     bytes = mmInStream.read(buffer);
     mHandler.obtainMessage(weixinFragment.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
    } catch (IOException e) {
     connectionLost();
     break;
    }
   }
  }

  public void write(byte[] buffer) {
   try {
    mmOutStream.write(buffer);
    mHandler.obtainMessage(weixinFragment.MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
   } catch (IOException e) {
    e.printStackTrace();
   }
  }

  public void cancel() {
   try {
    mmSocket.close();
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
 }

新建Activity組件DeviceList,實(shí)現(xiàn)拾取與之會(huì)話的藍(lán)牙設(shè)備。本程序供菜單項(xiàng)主界面的選項(xiàng)菜單“我的友好”調(diào)用,用于:

(1)顯示已配對(duì)的好友列表;
(2)搜索可配對(duì)的好友進(jìn)行配對(duì)
(3)新選擇并配對(duì)的藍(lán)牙設(shè)備將刷新好友列表

注意:發(fā)現(xiàn)新的藍(lán)牙設(shè)備并請(qǐng)求配對(duì)時(shí),需要對(duì)應(yīng)接受

關(guān)鍵技術(shù):動(dòng)態(tài)注冊(cè)一個(gè)廣播接收者,處理藍(lán)牙設(shè)備掃描的結(jié)果

public class DeviceList extends Activity{
  private BluetoothAdapter mBtAdapter;
  private ArrayAdapter<String> mPairedDevicesArrayAdapter;
  private ArrayAdapter<String> mNewDevicesArrayAdapter;
  public static String EXTRA_DEVICE_ADDRESS = "device_address"; //Mac地址
  //定義廣播接收者,用于處理掃描藍(lán)牙設(shè)備后的結(jié)果
  private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
   @Override
   public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();
    if (BluetoothDevice.ACTION_FOUND.equals(action)) {
     BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
     if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
      mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
     }
    } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
     if (mNewDevicesArrayAdapter.getCount() == 0) {
      String noDevices = getResources().getText(R.string.none_found).toString();
      mNewDevicesArrayAdapter.add(noDevices);
     }
    }
   }
  };
  @Override
  protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.device_list);
   //在被調(diào)用活動(dòng)里,設(shè)置返回結(jié)果碼
   setResult(Activity.RESULT_CANCELED);
   init(); //活動(dòng)界面
  }
  private void init() {
   Button scanButton = findViewById(R.id.button_scan);
   scanButton.setOnClickListener(new OnClickListener() {
    public void onClick(View v) {
     Toast.makeText(DeviceList.this, R.string.scanning, Toast.LENGTH_LONG).show();
     doDiscovery(); //搜索藍(lán)牙設(shè)備
    }
   });
   mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);
   mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);
   //已配對(duì)藍(lán)牙設(shè)備列表
   ListView pairedListView =findViewById(R.id.paired_devices);
   pairedListView.setAdapter(mPairedDevicesArrayAdapter);
   pairedListView.setOnItemClickListener(mPaireDeviceClickListener);
   //未配對(duì)藍(lán)牙設(shè)備列表
   ListView newDevicesListView = findViewById(R.id.new_devices);
   newDevicesListView.setAdapter(mNewDevicesArrayAdapter);
   newDevicesListView.setOnItemClickListener(mNewDeviceClickListener);
   //動(dòng)態(tài)注冊(cè)廣播接收者
   IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
   registerReceiver(mReceiver, filter);
   filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
   registerReceiver(mReceiver, filter);
   mBtAdapter = BluetoothAdapter.getDefaultAdapter();
   Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();
   if (pairedDevices.size() > 0) {
    findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);
    for (BluetoothDevice device : pairedDevices) {
     mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
    }
   } else {
    String noDevices = getResources().getText(R.string.none_paired).toString();
    mPairedDevicesArrayAdapter.add(noDevices);
   }
  }
  @Override
  protected void onDestroy() {
   super.onDestroy();
   if (mBtAdapter != null) {
    mBtAdapter.cancelDiscovery();
   }
   this.unregisterReceiver(mReceiver);
  }
  private void doDiscovery() {
   findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE);
   if (mBtAdapter.isDiscovering()) {
    mBtAdapter.cancelDiscovery();
   }
   mBtAdapter.startDiscovery(); //開始搜索藍(lán)牙設(shè)備并產(chǎn)生廣播
    //startDiscovery是一個(gè)異步方法
   //找到一個(gè)設(shè)備時(shí)就發(fā)送一個(gè)BluetoothDevice.ACTION_FOUND的廣播
  }
  private OnItemClickListener mPaireDeviceClickListener = new OnItemClickListener() {
   public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {
    mBtAdapter.cancelDiscovery();
    String info = ((TextView) v).getText().toString();
    String address = info.substring(info.length() - 17);
    Intent intent = new Intent();
    intent.putExtra(EXTRA_DEVICE_ADDRESS, address); //Mac地址
    setResult(Activity.RESULT_OK, intent);
    finish();
   }
  };
  private OnItemClickListener mNewDeviceClickListener = new OnItemClickListener() {
   public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {
    mBtAdapter.cancelDiscovery();
    Toast.makeText(DeviceList.this, "請(qǐng)?jiān)谒{(lán)牙設(shè)置界面手動(dòng)連接設(shè)備",Toast.LENGTH_SHORT).show();
    Intent intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
    startActivityForResult(intent,1);
   }
  };
  //回調(diào)方法:進(jìn)入藍(lán)牙配對(duì)設(shè)置界面返回后執(zhí)行
  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   super.onActivityResult(requestCode, resultCode, data);
   init(); //刷新好友列表
  }
 }

藍(lán)牙會(huì)話的主Activity組件程序fragment.java

public class weixinFrament extends Fragment {
 public static final int MESSAGE_STATE_CHANGE = 1;
 public static final int MESSAGE_READ = 2;
 public static final int MESSAGE_WRITE = 3;
 public static final int MESSAGE_DEVICE_NAME = 4;
 public static final int MESSAGE_TOAST = 5;
 public static final String DEVICE_NAME = "device_name";
 public static final String TOAST = "toast";
 private static final int REQUEST_CONNECT_DEVICE = 1; //請(qǐng)求連接設(shè)備
 private static final int REQUEST_ENABLE_BT = 2;
 private TextView mTitle;
 private ListView mConversationView;
 private EditText mOutEditText;
 private Button mSendButton;
 private String mConnectedDeviceName = null;
 private ArrayAdapter<String> mConversationArrayAdapter;
 private StringBuffer mOutStringBuffer;
 private BluetoothAdapter mBluetoothAdapter = null;
 private ChatService mChatService = null;

 private View view;

 public weixinFrament() {

 }

 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

  view = inflater.inflate(R.layout.tab_01, container, false);

  Toolbar toolbar = view.findViewById(R.id.toolbar);
  setHasOptionsMenu(true);

  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
   if (ContextCompat.checkSelfPermission(this.getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
   }
  }

  //創(chuàng)建選項(xiàng)菜單
  toolbar.inflateMenu(R.menu.option_menu);
  //選項(xiàng)菜單監(jiān)聽
  toolbar.setOnMenuItemClickListener(new MyMenuItemClickListener());
  mTitle = view.findViewById(R.id.title_left_text);
  mTitle.setText(R.string.app_name);
  mTitle = view.findViewById(R.id.title_right_text);
  // 得到本地藍(lán)牙適配器
  mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
  if (mBluetoothAdapter == null) {
   Toast.makeText(view.getContext(), "藍(lán)牙不可用", Toast.LENGTH_LONG).show();
   getActivity().finish();
   return view;
  }
  if (!mBluetoothAdapter.isEnabled()) { //若當(dāng)前設(shè)備藍(lán)牙功能未開啟
   Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
   startActivityForResult(enableIntent, REQUEST_ENABLE_BT); //
  } else {
   if (mChatService == null) {
    setupChat(); //創(chuàng)建會(huì)話
   }
  }

  return view;
 }

 @Override
 public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
  super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  if (grantResults.length > 0) {
   if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
    Toast.makeText(view.getContext(), "未授權(quán),藍(lán)牙搜索功能將不可用!", Toast.LENGTH_SHORT).show();
   }
  }
 }

 @Override
 public synchronized void onResume() { //synchronized:同步方法實(shí)現(xiàn)排隊(duì)調(diào)用
  super.onResume();
  if (mChatService != null) {
   if (mChatService.getState() == ChatService.STATE_NONE) {
    mChatService.start();
   }
  }
 }

 private void setupChat() {
  mConversationArrayAdapter = new ArrayAdapter<String>(view.getContext(), R.layout.message);
  mConversationView = view.findViewById(R.id.in);
  mConversationView.setAdapter(mConversationArrayAdapter);
  mOutEditText = view.findViewById(R.id.edit_text_out);
  mOutEditText.setOnEditorActionListener(mWriteListener);
  mSendButton = view.findViewById(R.id.button_send);
  mSendButton.setOnClickListener(new View.OnClickListener() {
   public void onClick(View v) {
    TextView textview = view.findViewById(R.id.edit_text_out);
    String message = textview.getText().toString();
    sendMessage(message);
   }
  });
  //創(chuàng)建服務(wù)對(duì)象
  mChatService = new ChatService(view.getContext(), mHandler);
  mOutStringBuffer = new StringBuffer("");
 }

 @Override
 public void onDestroy() {
  super.onDestroy();
  if (mChatService != null)
   mChatService.stop();
 }

 private void ensureDiscoverable() { //修改本機(jī)藍(lán)牙設(shè)備的可見性
  //打開手機(jī)藍(lán)牙后,能被其它藍(lán)牙設(shè)備掃描到的時(shí)間不是永久的
  if (mBluetoothAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
   Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
   //設(shè)置在300秒內(nèi)可見(能被掃描)
   discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
   startActivity(discoverableIntent);
   Toast.makeText(view.getContext(), "已經(jīng)設(shè)置本機(jī)藍(lán)牙設(shè)備的可見性,對(duì)方可搜索了。", Toast.LENGTH_SHORT).show();
  }
 }

 private void sendMessage(String message) {
  if (mChatService.getState() != ChatService.STATE_CONNECTED) {
   Toast.makeText(view.getContext(), R.string.not_connected, Toast.LENGTH_SHORT).show();
   return;
  }
  if (message.length() > 0) {
   byte[] send = message.getBytes();
   mChatService.write(send);
   mOutStringBuffer.setLength(0);
   mOutEditText.setText(mOutStringBuffer);
  }
 }

 private TextView.OnEditorActionListener mWriteListener = new TextView.OnEditorActionListener() {
  @Override
  public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
   if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) {
    //軟鍵盤里的回車也能發(fā)送消息
    String message = view.getText().toString();
    sendMessage(message);
   }
   return true;
  }
 };
 //使用Handler對(duì)象在UI主線程與子線程之間傳遞消息
 private final Handler mHandler = new Handler() { //消息處理
  @Override
  public void handleMessage(Message msg) {
   switch (msg.what) {
    case MESSAGE_STATE_CHANGE:
     switch (msg.arg1) {
      case ChatService.STATE_CONNECTED:
       mTitle.setText(R.string.title_connected_to);
       mTitle.append(mConnectedDeviceName);
       mConversationArrayAdapter.clear();
       break;
      case ChatService.STATE_CONNECTING:
       mTitle.setText(R.string.title_connecting);
       break;
      case ChatService.STATE_LISTEN:
      case ChatService.STATE_NONE:
       mTitle.setText(R.string.title_not_connected);
       break;
     }
     break;
    case MESSAGE_WRITE:
     byte[] writeBuf = (byte[]) msg.obj;
     String writeMessage = new String(writeBuf);
     mConversationArrayAdapter.add("我: " + writeMessage);
     break;
    case MESSAGE_READ:
     byte[] readBuf = (byte[]) msg.obj;
     String readMessage = new String(readBuf, 0, msg.arg1);
     mConversationArrayAdapter.add(mConnectedDeviceName + ": "
       + readMessage);
     break;
    case MESSAGE_DEVICE_NAME:
     mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
     Toast.makeText(getActivity().getApplicationContext(), "鏈接到 " + mConnectedDeviceName, Toast.LENGTH_SHORT).show();
     break;
    case MESSAGE_TOAST:
     Toast.makeText(getActivity().getApplicationContext(),
       msg.getData().getString(TOAST), Toast.LENGTH_SHORT).show();
     break;
   }
  }
 };

 //返回進(jìn)入好友列表操作后的數(shù)回調(diào)方法
 public void onActivityResult(int requestCode, int resultCode, Intent data) {
  switch (requestCode) {
   case REQUEST_CONNECT_DEVICE:
    if (resultCode == Activity.RESULT_OK) {
     String address = data.getExtras().getString(DeviceList.EXTRA_DEVICE_ADDRESS);
     BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
     mChatService.connect(device);
    } else if (resultCode == Activity.RESULT_CANCELED) {
     Toast.makeText(view.getContext(), "未選擇任何好友!", Toast.LENGTH_SHORT).show();
    }
    break;
   case REQUEST_ENABLE_BT:
    if (resultCode == Activity.RESULT_OK) {
     setupChat();
    } else {
     Toast.makeText(view.getContext(), R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();
     getActivity().finish();
    }
  }
 }

 //內(nèi)部類,選項(xiàng)菜單的單擊事件處理
 private class MyMenuItemClickListener implements Toolbar.OnMenuItemClickListener {
  @Override
  public boolean onMenuItemClick(MenuItem item) {
   switch (item.getItemId()) {
    case R.id.scan:
     //啟動(dòng)DeviceList這個(gè)Activity
     Intent serverIntent = new Intent(weixinFrament.this.getActivity(), DeviceList.class);
     startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
     return true;
    case R.id.discoverable:
     ensureDiscoverable();
     return true;
    case R.id.back:
     getActivity().finish();
     System.exit(0);
     return true;
   }
   return false;
  }
 }
}

項(xiàng)目地址

點(diǎn)我進(jìn)入倉(cāng)庫(kù)

總結(jié)

到此這篇關(guān)于Android在類微信程序中實(shí)現(xiàn)藍(lán)牙聊天功能的文章就介紹到這了,更多相關(guān)android 類微信程序藍(lán)牙聊天內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Android使用SmsManager實(shí)現(xiàn)短信發(fā)送功能

    Android使用SmsManager實(shí)現(xiàn)短信發(fā)送功能

    這篇文章主要為大家詳細(xì)介紹了Android使用SmsManager實(shí)現(xiàn)短信發(fā)送功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • Android ViewModel的作用深入講解

    Android ViewModel的作用深入講解

    這篇文章主要介紹了Android ViewModel的作用,ViewModel類旨在以注重生命周期的方式存儲(chǔ)和管理界面相關(guān)數(shù)據(jù),ViewModel類讓數(shù)據(jù)可在發(fā)生屏幕旋轉(zhuǎn)等配置更改后繼續(xù)留存,需要詳細(xì)了解可以參考下文
    2023-05-05
  • Android中AutoCompleteTextView自動(dòng)提示

    Android中AutoCompleteTextView自動(dòng)提示

    這篇文章主要為大家詳細(xì)介紹了Android中AutoCompleteTextView自動(dòng)提示的實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • Android?FileProvider使用教程

    Android?FileProvider使用教程

    主要摘要關(guān)鍵知識(shí)點(diǎn)和記錄我的學(xué)習(xí)思路及驗(yàn)證結(jié)論,可以幫助讀者比較全面的認(rèn)識(shí)FileProvider,F(xiàn)ileProvider是特殊的ContentProvider,目標(biāo)是在為保護(hù)隱私和數(shù)據(jù)安全而加強(qiáng)應(yīng)用沙箱機(jī)制的同時(shí),支持在應(yīng)用間共享文件
    2023-03-03
  • Android Build Variants 為項(xiàng)目設(shè)置變種版本的方法

    Android Build Variants 為項(xiàng)目設(shè)置變種版本的方法

    下面小編就為大家分享一篇Android Build Variants 為項(xiàng)目設(shè)置變種版本的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • Android手機(jī)拍照或選取圖庫(kù)圖片作為頭像

    Android手機(jī)拍照或選取圖庫(kù)圖片作為頭像

    這篇文章主要介紹了Android手機(jī)拍照或選取圖庫(kù)圖片作為頭像的相關(guān)資料,需要的朋友可以參考下
    2015-06-06
  • Android仿抖音右滑清屏左滑列表功能的實(shí)現(xiàn)代碼

    Android仿抖音右滑清屏左滑列表功能的實(shí)現(xiàn)代碼

    這篇文章主要介紹了Android仿抖音右滑清屏左滑列表功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06
  • Android利用Canvas標(biāo)點(diǎn)畫線并加入位移動(dòng)畫(2)

    Android利用Canvas標(biāo)點(diǎn)畫線并加入位移動(dòng)畫(2)

    這篇文章主要為大家詳細(xì)介紹了Android利用Canvas標(biāo)點(diǎn)畫線并加入位移動(dòng)畫的第二篇,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-09-09
  • Android BindService使用案例講解

    Android BindService使用案例講解

    這篇文章主要介紹了Android BindService使用案例講解,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • Flutter上的數(shù)據(jù)監(jiān)控深入理解

    Flutter上的數(shù)據(jù)監(jiān)控深入理解

    這篇文章主要給大家介紹了關(guān)于Flutter上的數(shù)據(jù)監(jiān)控的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Flutter具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06

最新評(píng)論