380 likes | 594 Views
Android 傳送檔案. 建國科技大學 資管系 饒瑞佶 2013/7 V1. Android 傳送檔案. 透過 Intent 透過 BluetoothShare.java 部分 SDK 不能使用 透過標準 Bluetooth Service 與 socket Client vs. Server. 需要的權限. <uses-permission android:name= "android.permission.BLUETOOTH"/>
E N D
Android傳送檔案 建國科技大學 資管系 饒瑞佶 2013/7 V1
Android傳送檔案 • 透過Intent • 透過BluetoothShare.java • 部分SDK不能使用 • 透過標準Bluetooth Service與socket • Client vs. Server
需要的權限 • <uses-permission android:name="android.permission.BLUETOOTH"/> • <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> • <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
提醒 • 手機需要開啟藍芽 • 需要設定成可以被偵測
透過Intent publicclassBT_Intentextends Activity { @Override publicvoidonCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.btintent); // 按傳送按鈕 Button scanButton = (Button) findViewById(R.id.button_send); scanButton.setOnClickListener(newOnClickListener() { publicvoidonClick(View v) { Intent intent=new Intent(); intent.setAction(Intent.ACTION_SEND); intent.setType("image/*"); intent.putExtra(Intent.EXTRA_STREAM,Uri.fromFile(new File("/sdcard/translate.png"))); startActivity(intent); } }); } } Sdcard卡內檔案
透過標準Bluetooth Service與socketServer-onCreate @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); image = (ImageView) findViewById(R.id.imageView1); mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (mBluetoothAdapter == null) { Toast.makeText(this,"Bluetooth is not available.",Toast.LENGTH_LONG).show(); finish(); return; }
透過標準Bluetooth Service與socketServer -onCreate if (!mBluetoothAdapter.isEnabled()) { Toast.makeText(this,"Please enable your BT and re-run this program.",Toast.LENGTH_LONG).show(); finish(); return; } tv=(TextView) findViewById(R.id.textView1); tv.setText("請開啟接收!"); tv.setTextColor(Color.BLUE); // 按掃描按鈕,啟動掃描藍芽設備 Button scanButton = (Button) findViewById(R.id.button_scan); scanButton.setOnClickListener(new OnClickListener() { publicvoid onClick(View v) { AcceptData acceptData = new AcceptData(); acceptData.start(); Bitmap bm1 = BitmapFactory.decodeByteArray(buffer, 0, buffer.length); image.setImageBitmap(bm1); } }); }
透過標準Bluetooth Service與socketServer-class AcceptData // 接收圖片 class AcceptData extends Thread{ privatefinal BluetoothServerSocket mmServerSocket; private BluetoothSocket socket = null; private InputStream mmInStream; private String device; public AcceptData() { BluetoothServerSocket tmp = null; try { tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord("Bluetooth", MY_UUID); } catch (IOException e) { // }
透過標準Bluetooth Service與socketServer -class AcceptData mmServerSocket = tmp; try { socket = mmServerSocket.accept(); } catch (IOException e) { // } device = socket.getRemoteDevice().getName(); Toast.makeText(getBaseContext(), "接收來自 "+ device + " 的資料", Toast.LENGTH_SHORT).show(); InputStream tmpIn = null; try { tmpIn = socket.getInputStream(); } catch (IOException e) { // }
透過標準Bluetooth Service與socketServer -class AcceptData mmInStream = tmpIn; int byteNo; try { byteNo = mmInStream.read(buffer); if (byteNo != -1) { //ensure DATAMAXSIZE Byte is read. int byteNo2 = byteNo; int bufferSize = 500000; //7340; while(byteNo2 != bufferSize){ bufferSize = bufferSize - byteNo2; byteNo2 = mmInStream.read(buffer,byteNo,bufferSize); if(byteNo2 == -1){ break; } byteNo = byteNo+byteNo2; } }
透過標準Bluetooth Service與socketServer -class AcceptData if (socket != null) { try { mmServerSocket.close(); tv.setText("請重新開啟接收!"); tv.setTextColor(Color.RED); } catch (IOException e) { // } } } catch (Exception e) { try { mmServerSocket.close(); tv.setText("請重新開啟接收!"); tv.setTextColor(Color.RED); } catch (IOException e1) { e1.printStackTrace(); } } } }
透過標準Bluetooth Service與socketServer -menu @Override publicbooleanonCreateOptionsMenu(Menu menu) { menu.add(0, 1, 1, "傳送圖片").setIcon(android.R.drawable.ic_menu_help); menu.add(0, 2, 2, "結束").setIcon(android.R.drawable.ic_menu_close_clear_cancel); returnsuper.onCreateOptionsMenu(menu); } @Override publicbooleanonOptionsItemSelected(MenuItem item) { switch(item.getItemId()){ case 1: Intent it=new Intent(Sendingdata_serverActivity.this,SendingdataActivity.class); startActivity(it); this.finish(); break; case 2: this.finish(); break; } returnsuper.onOptionsItemSelected(item); }
layout <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <ImageView android:id="@+id/imageView1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="xxx" android:textSize="20sp" /> <Button android:id="@+id/button_scan" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="開啟接收" /> </LinearLayout>
透過標準Bluetooth Service與socketClient-onCreate @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); setContentView(R.layout.client); //判斷設備是否支援藍芽 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (mBluetoothAdapter == null) { Toast.makeText(this,"您的設備不支援藍芽!",Toast.LENGTH_LONG).show(); finish(); return; }
透過標準Bluetooth Service與socketClient-onCreate // 如果藍芽沒有開啟,會要求開啟 if (!mBluetoothAdapter.isEnabled()) { Toast.makeText(this,"請開啟藍芽!",Toast.LENGTH_LONG).show(); Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent,REQUEST_ENABLE_BT); } setResult(Activity.RESULT_CANCELED); // 按掃描按鈕,啟動掃描藍芽設備 Button scanButton = (Button) findViewById(R.id.button_scan); scanButton.setOnClickListener(new OnClickListener() { publicvoid onClick(View v) { doDiscovery(); v.setVisibility(View.GONE); } });
透過標準Bluetooth Service與socketClient-onCreate //已配對設備列表 mArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name); ListView pairedListView = (ListView) findViewById(R.id.paired_devices); pairedListView.setAdapter(mArrayAdapter); // 設定按了後的事件 pairedListView.setOnItemClickListener(mDeviceClickListener); //其他設備列表 mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name); ListView newDevicesListView = (ListView) findViewById(R.id.new_devices); newDevicesListView.setAdapter(mNewDevicesArrayAdapter);
透過標準Bluetooth Service與socketClient-onCreate // 設定按了後的事件 pairedListView.setOnItemClickListener(mDeviceClickListener); //其他設備列表 mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name); ListView newDevicesListView = (ListView) findViewById(R.id.new_devices); newDevicesListView.setAdapter(mNewDevicesArrayAdapter); // 設定按了後的事件 newDevicesListView.setOnItemClickListener(mDeviceClickListener);
透過標準Bluetooth Service與socketClient-onCreate // 註冊廣播,回報設備掃描 IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); this.registerReceiver(mReceiver, filter); // 註冊廣播,回報設備掃描完成 filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); this.registerReceiver(mReceiver, filter); Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices(); // 如果有配對的設備 if (pairedDevices.size() > 0) { // 將所有配對列表加入 for (BluetoothDevice device : pairedDevices) {
透過標準Bluetooth Service與socketClient-onCreate // 將設備名稱與MAC加入列表 mArrayAdapter.add(device.getName() + "\n" + device.getAddress()); } }else{ mArrayAdapter.add("沒發現設備"); } // 傳送圖片 Button sendButton = (Button) findViewById(R.id.send); sendButton.setOnClickListener(new OnClickListener() { publicvoid onClick(View view) { if("".equals(address)){ Toast.makeText(SendingdataActivity.this,"您尚未選擇傳送對象!",Toast.LENGTH_LONG).show(); return; }else{ SendData sendData = new SendData(); sendData.sendMessage(); } } }); }
透過標準Bluetooth Service與socketClient-doDiscovery() // 掃描設備 privatevoid doDiscovery() { // 設定是窗抬頭 setProgressBarIndeterminateVisibility(true); setTitle("掃描中,請稍待"); // 開啟其他設備標題 findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE); // 掃描完成,停止 if (mBluetoothAdapter.isDiscovering()) { mBluetoothAdapter.cancelDiscovery(); } // 開始掃描 mBluetoothAdapter.startDiscovery(); }
透過標準Bluetooth Service與socketClient-BroadcastReceiver // BroadcastReceiver privatefinal BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override publicvoid onReceive(Context context, Intent intent) { String action = intent.getAction(); // 如果有發現任何藍芽設備 if (BluetoothDevice.ACTION_FOUND.equals(action)) { // 透過INTENT取得其他藍芽設備 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // 略過已配對設備,加入新其他設備 if (device.getBondState() != BluetoothDevice.BOND_BONDED) { mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress()); } // 搜尋結束後,更改抬頭 } elseif (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { setProgressBarIndeterminateVisibility(false); setTitle("請選擇設備"); if (mNewDevicesArrayAdapter.getCount() == 0) { mNewDevicesArrayAdapter.add("沒發現設備"); } } } };
透過標準Bluetooth Service與socketClient-OnItemClickListener // 按了列表上的某個設備後進行的動作 private OnItemClickListener mDeviceClickListener = new OnItemClickListener() { publicvoid onItemClick(AdapterView<?> av, View v, int arg2, long arg3) { // 取得設備 MAC address String info = ((TextView) v).getText().toString(); address = info.substring(info.length() - 17); //藍芽設備 MAC Toast.makeText(SendingdataActivity.this,"選擇傳送到"+ info,Toast.LENGTH_LONG).show(); } };
透過標準Bluetooth Service與socketClient-SendData //傳送檔案 class SendData extends Thread { private BluetoothDevice device = null; private BluetoothSocket btSocket = null; private OutputStream outStream = null; public SendData(){ device = mBluetoothAdapter.getRemoteDevice(address); try { btSocket = device.createRfcommSocketToServiceRecord(MY_UUID); } catch (Exception e) { // TODO: handle exception } mBluetoothAdapter.cancelDiscovery();
透過標準Bluetooth Service與socketClient-SendData try { btSocket.connect(); } catch (IOException e) { try { btSocket.close(); } catch (IOException e2) { } } Toast.makeText(getBaseContext(), "Connected to " + device.getName(), Toast.LENGTH_SHORT).show(); try { outStream = btSocket.getOutputStream(); } catch (IOException e) { } }
透過標準Bluetooth Service與socketClient-SendData publicvoid sendMessage() { try { //mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); //sdcard內圖片 String imgFilePath = Environment.getExternalStorageDirectory().toString() + "/translate.png"; FileInputStream fis = new FileInputStream(new File(imgFilePath)); Bitmap bm = BitmapFactory.decodeStream(fis); //Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); ByteArrayOutputStream baos = new ByteArrayOutputStream();
透過標準Bluetooth Service與socketClient-SendData bm.compress(Bitmap.CompressFormat.JPEG, 100,baos); //bm is the bitmap object byte[] b = baos.toByteArray(); //Toast.makeText(getBaseContext(), "size:" + String.valueOf(b.length), Toast.LENGTH_SHORT).show(); outStream.write(b); outStream.flush(); outStream.close(); btSocket.close(); } catch (IOException e) { return; } } }
透過標準Bluetooth Service與socketClient-onDestroy // 取消BluetoothAdapter與廣播註冊 @Override protectedvoid onDestroy() { if (mBluetoothAdapter != null) { mBluetoothAdapter.cancelDiscovery(); } // Unregister broadcast listeners this.unregisterReceiver(mReceiver); super.onDestroy(); }
透過標準Bluetooth Service與socketClient-menu //設定menu選項 @Override publicboolean onCreateOptionsMenu(Menu menu) { menu.add(0, 1, 1, "接收圖片").setIcon(android.R.drawable.ic_menu_help); menu.add(0, 2, 2, "結束").setIcon(android.R.drawable.ic_menu_close_clear_cancel); returnsuper.onCreateOptionsMenu(menu); } @Override publicboolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()){ case 1: Intent it=new Intent(SendingdataActivity.this,Sendingdata_serverActivity.class); startActivity(it); this.finish(); break; case 2: this.finish(); break; } returnsuper.onOptionsItemSelected(item); }
layout <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/title_paired_devices" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="已配對設備" android:visibility="gone" android:background="#666" android:textColor="#fff" android:paddingLeft="5dp" /> <ListView android:id="@+id/paired_devices" android:layout_width="match_parent" android:layout_height="wrap_content" android:stackFromBottom="true" android:layout_weight="1" />
layout <TextView android:id="@+id/title_new_devices" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="其他設備" android:visibility="gone" android:background="#666" android:textColor="#fff" android:paddingLeft="5dp" /> <ListView android:id="@+id/new_devices" android:layout_width="match_parent" android:layout_height="wrap_content" android:stackFromBottom="true" android:layout_weight="2" /> <Button android:id="@+id/button_scan" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="掃描設備" /> <Button android:id="@+id/send" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="傳送圖片" /> </LinearLayout>
device_name.xml <?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="18sp" android:padding="5dp" />
透過BluetoothShare.java publicclass BT_bluetoothshare extends Activity { @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.btintent); // 按傳送按鈕 Button scanButton = (Button) findViewById(R.id.button_send); scanButton.setOnClickListener(new OnClickListener() { publicvoid onClick(View v) { sendfile("38:E7:D8:2C:6D:BB"); Toast.makeText(BT_bluetoothshare.this,"ok",Toast.LENGTH_LONG).show(); } }); } // 傳送檔案 publicvoid sendfile(String deviceMAC){ ContentValues values = new ContentValues(); values.put(BluetoothShare.URI, "file:///sdcard/chc.db"); values.put(BluetoothShare.DESTINATION, deviceMAC); values.put(BluetoothShare.DIRECTION, BluetoothShare.DIRECTION_OUTBOUND); Long ts = System.currentTimeMillis(); values.put(BluetoothShare.TIMESTAMP, ts); getContentResolver().insert(BluetoothShare.CONTENT_URI, values); } }