ورود

View Full Version : انتقال داده بین گوشی ها



suraty
دوشنبه 15 تیر 1394, 22:41 عصر
سلام، برای انتقال داده بین گوشی های اندروید چه راه حلی پیشنهاد می کنید؟ یک گوشی حالت سرور و بقیه به شکل کلاینت هستند.
گاه ارسال شکل همه پخشی و گاه به صورت مبادله دو طرفه است. همه پخشی فقط در ابتدای کار و توسط سرور صورت می گیرد.
در صورت امکان ممنون می شوم با نمونه کد و یا لینک هایی راهنمایی ام نمایید.
متشکرم

mnakhaeipoor
سه شنبه 16 تیر 1394, 16:49 عصر
سلام، برای انتقال داده بین گوشی های اندروید چه راه حلی پیشنهاد می کنید؟ یک گوشی حالت سرور و بقیه به شکل کلاینت هستند.
گاه ارسال شکل همه پخشی و گاه به صورت مبادله دو طرفه است. همه پخشی فقط در ابتدای کار و توسط سرور صورت می گیرد.
در صورت امکان ممنون می شوم با نمونه کد و یا لینک هایی راهنمایی ام نمایید.
متشکرم
سلام
بهترین و راحت ترین راه استفاده از روش ارتباطی peer to peer هست
برای استفاده از این راه ارتباطی اندروید فریم ورک wi-fip2p رو ارائه داده که استفاده از اون بسیار ساده هست و همون چیزی هست که شما دنبالش هستید
در جریان باشید که این فریم ورک مال API 14 و 14 به بالا هست
من توضیح مختصری در این رابطه میدم بقیه اش با خودتونه چون اگه بخوام کل آموزش رو بنویسم تا شب باید بنویسم!!
این توضیحات فقط برای اینه که حساب کار بیاد دستتون بعدش دیگه راحت میتونید خودتون مطلب رو یاد بگیرید...

اول از حضرت مانیفست شروع میکنیم :


<uses-sdk android:minSdkVersion="14" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />


بعد باید چک کنید ببینید اصن دستگاه از وای فای پشتیبانی میکنه یا نه اینطوری :


int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE , -1);
if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
// Wifi P2P is enabled
} else {
// Wi-Fi P2P is not enabled
}


وقتی وضعیت وای فای دستگاه تغییر میکنه اینتنت WIFI_P2P_STATE_CHANGED_ACTION منتشر میشه
پس گام بعدی اینه که یک برادکست برای اینتنت بالا بنویسید که بعدا باید یه سری کارا رو اونجا انجام بدید
بعد در اکتیویتی اصلیتون از این برادکستی که ایجاد کردید یه نمونه میگیرید تا بشه باهاش ور رفت


WifiP2pManager mManager;
Channel mChannel;
BroadcastReceiver mReceiver;
...
@Override
protected void onCreate(Bundle savedInstanceState){
...
mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
mChannel = mManager.initialize(this, getMainLooper(), null);
mReceiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this);
...
}


متد initialize از کلاس wifip2pManager اپلیکیشن شما رو در فریم ورک wifip2p ثبت میکنه
در مرحله بعد یه اینتنت فیلتر ایجاد کن تا وضعیت های مختلف وای فای رو دریافت بتونی بکنی


IntentFilter mIntentFilter;
...
@Override
protected void onCreate(Bundle savedInstanceState){
...
mIntentFilter = new IntentFilter();
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_ST ATE_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PE ERS_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CO NNECTION_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_TH IS_DEVICE_CHANGED_ACTION);
...
}


حالا برادکستی که در onCreate ایجاد کردی رو تو onResume رجیستر و تو onPause انرجیستر میکنی


/* register the broadcast receiver with the intent values to be matched */
@Override
protected void onResume() {
super.onResume();
registerReceiver(mReceiver, mIntentFilter);
}
/* unregister the broadcast receiver */
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mReceiver);
}





خب تا اینجای کار ما یک کانال وای فای توسط WifiP2pManager.Channel (در onCreate) ایجاد کردیم و برادکست رسیور برای دریافت و بررسی اینتنت های فریم ورک Wi-Fi P2P رو هم ایجاد کردیم :تشویق::تشویق:
پس حالا میتونیم با استفاده از متد های کلاس WifiP2pManager اقدام به
1 - کشف peer های مجاور
2 - اتصال به peer
و نهایتا 3- مبادله داده بین peer ها
بکنیم
خب ! پس شروع میکنیم :

1 - کشف peer های مجاور

اینکار خیلی راحته با استفاده از متد discoverPeers() میتونیم بفهمیم نقطه ای برا اتصال وجود داره یا نه


mManager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
...
}


@Override
public void onFailure(int reasonCode) {
...
}
});


آرگومان اول که کانالی هست که ساختیم و آرگومان دوم هم یک listener هست که نتیجه رو اعلام میکنه
اگه نقطه ای برای اتصال پیدا شد متد onSuccess و در غیر اینصورت متد onFailure صدا زده میشه
در مرحله بعد اگر سیستم موفق شد نقطه ی اتصال فعالی رو کشف کنه اینتنت WIFI_P2P_PEERS_CHANGED_ACTION برادکست میشه
این اینتنت همونیه که در مراحل قبلی به عنوان یک اینتنت فیلتر به برادکست رسیوری که ساخته بودیم متصلش کردیم
پس اگر نقطه ی اتصالی پیدا شد متد onReceive فراخوانی میشه و ما در این قسمت قادر خواهیم بود تا لیستی از نقاط اتصال فعال به وجود بیاریم

...
if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equa ls(action)) {


if (manager != null) {
manager.requestPeers(channel, new WifiP2pManager.PeerListListener() {
@Override
public void onPeersAvailable(WifiP2pDeviceList peers) {
Log.d(TAG,String.format("PeerListListener: %d peers available, ", peers.getDeviceList().size()));


}
});
}
}


کاری که اینجا انجام میشه اینه که لیستی از نقاط فعال به متد onPeersAvailable() از WifiP2pManager.PeerListListener ارسال میشه و در متد onPeersAvailable() ما بالاخره میتونیم لیستی از نقاط فعال رو داشته باشیم!

2 - اتصال به peerهای مورد نظر

حالا که میدونیم نقطه اتصالی برای اتصال وجود داره کد زیر رو برای متصل شدن به نقطه داخل همون برادکستمون قرار میدیم (داخل متد onPeersAvailable) :


WifiP2pDevice device;
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = device.deviceAddress;
mManager.connect(mChannel, config, new ActionListener() {


@Override
public void onSuccess() {
//success logic
}


@Override
public void onFailure(int reason) {
//failure logic
}
});



متد connect به یک WifiP2pConfig نیاز داره WifiP2pConfig شامل اطلاعات دیوایسی هست که میخوایم بهش وصل بشیم (مثل آدرس MAC)
حالا اگر برقراری اتصال موفقیت آمیز بود متد onSuccess و در غیر اینصورت متد onFailure صدا زده میشه

3 - تبادل داده میان peer های متصل شده

خب حالا که اتصال برقرار شد میتونیم با کمک سوکت ها اقدام به مبادله اطلاعات بین دو دستگاه کنیم
اول یه ServerSocket ایجاد میکنیم این ServerSocket منتظر یک اتصال از جانب کلاینت خواهد ماند(روی یک پورت خاص) البته توجه داشته باشید که استفاده از ServerSocket توی نخ اصلی برنامه گناه کبیره محسوب میشه (تازه اونم تو ماه رمضون:متعجب:) و باید توی نخ پس زمینه اجراش کنید
بعد باید یک Socket کلاینت ایجاد کنید که از ادرس ای پی و پورت سوکت سرور برای تصال بهش استفاده میکنه
نهایتا وقتی اتصال کلاینت به سرور تکمیل شد میتونید از کلاینت به سرور بایت استریم بفرستید
دو مثال زیر چکیده ی صحبت هام در باب Socket هست که من از یک مثال کاربردی خود گوگل (https://github.com/ahmontero/wifi-direct-demo) کپیشون کردم


public static class FileServerAsyncTask extends AsyncTask {


private Context context;
private TextView statusText;


public FileServerAsyncTask(Context context, View statusText) {
this.context = context;
this.statusText = (TextView) statusText;
}


@Override
protected String doInBackground(Void... params) {
try {


/**
* Create a server socket and wait for client connections. This
* call blocks until a connection is accepted from a client
*/
ServerSocket serverSocket = new ServerSocket(8888);
Socket client = serverSocket.accept();


/**
* If this code is reached, a client has connected and transferred data
* Save the input stream from the client as a JPEG file
*/
final File f = new File(Environment.getExternalStorageDirectory() + "/"
+ context.getPackageName() + "/wifip2pshared-" + System.currentTimeMillis()
+ ".jpg");


File dirs = new File(f.getParent());
if (!dirs.exists())
dirs.mkdirs();
f.createNewFile();
InputStream inputstream = client.getInputStream();
copyFile(inputstream, new FileOutputStream(f));
serverSocket.close();
return f.getAbsolutePath();
} catch (IOException e) {
Log.e(WiFiDirectActivity.TAG, e.getMessage());
return null;
}
}


/**
* Start activity that can handle the JPEG image
*/
@Override
protected void onPostExecute(String result) {
if (result != null) {
statusText.setText("File copied - " + result);
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIE W);
intent.setDataAndType(Uri.parse("file://" + result), "image/*");
context.startActivity(intent);
}
}
}


کد بالا مربوط به سرور میشه که عکسی که از کلاینت دریافت کرده رو توی یک اکتیویتی نمایش میده
کد پایینی هم مربوط به کلاینت میشه که عکس رو برای سرور ارسال میکنه :


Context context = this.getApplicationContext();
String host;
int port;
int len;
Socket socket = new Socket();
byte buf[] = new byte[1024];
...
try {
/**
* Create a client socket with the host,
* port, and timeout information.
*/
socket.bind(null);
socket.connect((new InetSocketAddress(host, port)), 500);


/**
* Create a byte stream from a JPEG file and pipe it to the output stream
* of the socket. This data will be retrieved by the server device.
*/
OutputStream outputStream = socket.getOutputStream();
ContentResolver cr = context.getContentResolver();
InputStream inputStream = null;
inputStream = cr.openInputStream(Uri.parse("path/to/picture.jpg"));
while ((len = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, len);
}
outputStream.close();
inputStream.close();
} catch (FileNotFoundException e) {
//catch logic
} catch (IOException e) {
//catch logic
}


/**
* Clean up any open sockets when done
* transferring or if an exception occurred.
*/
finally {
if (socket != null) {
if (socket.isConnected()) {
try {
socket.close();
} catch (IOException e) {
//catch logic
}
}
}
}



کلا سر وکله زدن با سوکت جماعت یکم درد سر داره باید سیخکاریش کنید تا بفهمید چی به چیه
امیدوارم توضیحات اندکی که دادم جرقه ای بوده باشه برای شروع مبحث شیرین WiFi Direct و سوکت
موفق باشید...

suraty
چهارشنبه 17 تیر 1394, 18:18 عصر
سلام، واقعا ممنونم، خیلی عالی توضیح دادید. متشکرم.
اما من چند وقت پیش مشابه این برنامه رو دانلود کردم و روی گوشی خواستم تست کنم. متاسفانه انجام نشد! که به خاطرش این پست رو در سایت گذاشتم:
http://barnamenevis.org/showthread.php?499717-%D8%AA%D8%B3%D8%AA-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D8%A7%D8%B1%D8%AA%D8%A8%D8%A7%D8%B7-p2p-%D8%A7%D8%B2-%D8%B7%D8%B1%DB%8C%D9%82-wifi
حالا با توضیحاتی که شما ارائه فرمودید، فکر می کنم اتصال به مودم یا اینترنت اصلا احتیاج نیست و باید مثلا وضعیت وای فای رو دستی تغییر بدم که اینتنت WIFI_P2P_STATE_CHANGED_ACTION منتشر بشه؟
یا اینکه اشتباه می کنم و طور دیگه ای باید تست کنم؟ برنامه رو باز کنم و بعد ....
چطور peer های مجاور رو برام لیست می کنه؟؟
بازم ممنون

mnakhaeipoor
پنج شنبه 18 تیر 1394, 06:55 صبح
سلام، واقعا ممنونم، خیلی عالی توضیح دادید. متشکرم.
اما من چند وقت پیش مشابه این برنامه رو دانلود کردم و روی گوشی خواستم تست کنم. متاسفانه انجام نشد! که به خاطرش این پست رو در سایت گذاشتم:
http://barnamenevis.org/showthread.php?499717-%D8%AA%D8%B3%D8%AA-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D8%A7%D8%B1%D8%AA%D8%A8%D8%A7%D8%B7-p2p-%D8%A7%D8%B2-%D8%B7%D8%B1%DB%8C%D9%82-wifi
حالا با توضیحاتی که شما ارائه فرمودید، فکر می کنم اتصال به مودم یا اینترنت اصلا احتیاج نیست و باید مثلا وضعیت وای فای رو دستی تغییر بدم که اینتنت WIFI_P2P_STATE_CHANGED_ACTION منتشر بشه؟
یا اینکه اشتباه می کنم و طور دیگه ای باید تست کنم؟ برنامه رو باز کنم و بعد ....
چطور peer های مجاور رو برام لیست می کنه؟؟
بازم ممنون
سلام
در درجه اول بگم که این کار اصن ربطی به اینترنت و مودم و... نداره
ببینید وقتی وضعیت وای فای تغییر کرد (یعنی وای فای گوشی رو روشن کردید) اینتنت WIFI_P2P_STATE_CHANGED_ACTION منتشر میشه
حالا تو رسیوری که این اینتنت رو دریافت میکنه باید منتظر اینتنت WIFI_P2P_PEERS_CHANGED_ACTION باشید که وقتی منتشر میشه که یه نقطه اتصال فعال (یه گوشی دیگه که وای فایش روشنه) پیدا بشه بعد که این اینتنت (اینتنت WIFI_P2P_PEERS_CHANGED_ACTION) منتشر شد نوبت اینه که توی متد onPeersAvailable لیست نقاط فعال رو نمایش بدید
کلا لیست کردن پییر های مجاور همین قدر بیشتر کار نداره!
بازم اگر متوجه نشدید یه سر به این لینک (http://stackoverflow.com/questions/17530885/android-java-wifi-direct-peer-list) بزنید دقیقا سوال شما رو بهش جواب دادن میتونه براتون مفید باشه
اگر بازم مشکلتون حل نشد من در خدمتم
موفق باشید

suraty
پنج شنبه 18 تیر 1394, 19:38 عصر
سلام، بسیار ممنونم از لطف و عنایت شما. حالا مطالب خیلی واضح و روشن شده اند. در اسرع وقت با توضیحاتی که فرمودید مجددا با دو تا گوشی تست می کنم. امیدوارم نتیجه بخش باشه.
فقط در ابتدای پست قبلی شما بهترین راه برای سوال طرح شده اینجانب، روش wifi p2p رو ذکر کردید. آیا روش های دیگری هم مدنظرتون هست؟
مثلا با جستجوهایی که انجام دادم، ایجاد یک شبکه ad hoc؟ در واقع در ذهنم یک برنامه شبیه Zapya ست. که به گمانم از قابلیت ایجاد hotspot در گوشی استفاده می کنه.
شرمنده که سوال اینقدر شاخ و برگ گرفته. قصد من حصول اطمینان از اینه که بهترین و ممکن ترین راه برای انجام کاری که در نظر دارم همین راه است.
ممنونم

mnakhaeipoor
پنج شنبه 18 تیر 1394, 21:18 عصر
سلام، بسیار ممنونم از لطف و عنایت شما. حالا مطالب خیلی واضح و روشن شده اند. در اسرع وقت با توضیحاتی که فرمودید مجددا با دو تا گوشی تست می کنم. امیدوارم نتیجه بخش باشه.
فقط در ابتدای پست قبلی شما بهترین راه برای سوال طرح شده اینجانب، روش wifi p2p رو ذکر کردید. آیا روش های دیگری هم مدنظرتون هست؟
مثلا با جستجوهایی که انجام دادم، ایجاد یک شبکه ad hoc؟ در واقع در ذهنم یک برنامه شبیه Zapya ست. که به گمانم از قابلیت ایجاد hotspot در گوشی استفاده می کنه.
شرمنده که سوال اینقدر شاخ و برگ گرفته. قصد من حصول اطمینان از اینه که بهترین و ممکن ترین راه برای انجام کاری که در نظر دارم همین راه است.
ممنونم
متاسفانه من به دلیل یه چند تا پروژه فشرده که دارم کمتر توفیق خدمت رسانی دارم
اما این که سوالتون شاخ و برگ گرفته اصلا چیز بدی نیست:متعجب:
اینجا توی یک جامعه ی متن باز همه ی ما برنامه نویس ها جمع شدیم تا به همدیگه کمک کنیم و پیشرفت کنیم
پس سوالاتتون رو خیلی راحت بپرسید منم تا جایی که مخم کار میکنه در خدمتتون هستم:چشمک:
حقیقت امر من به شخصه فقط با همون wifi direct کار کردم و اینطور هم که به ذهنم رسیده زاپیا هم از همین روش استفاده میکنه
توضیحاتی هم که شما تو اولین تاپیکتون داده بودید رو خیلی راحت میشه با همین wifip2p پیاده سازی کرد
مسلما میشه از روش های دیگه هم استفاده کرد اما راهی که گوگل جلوی پای برنامه نویسا گذاشته استفاده از همین فریم ورک wifip2p هست که به نظر مقرون به صرفه ترین و مناسب ترین راه باشه
توصیه من هم به عنوان بهترین راه همین فریم ورک wifip2p هستش
سه تا ویدیوی آموزشی زیر از یوتیوب هم میتونه براتون مفید باشه :
لینک 1 (http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=6&cad=rja&uact=8&ved=0CEEQtwIwBQ&url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DwOC omLjdqDA&ei=WK-eVZTqHtS6ogSk-42oBg&usg=AFQjCNFxUFI66HmlvBHKoFxQVMJHCCZZCg&sig2=1NHAduUqnBAV59u9Y67Mbw&bvm=bv.96952980,d.cGU)
لینک 2 (http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=7&cad=rja&uact=8&ved=0CEcQtwIwBg&url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Dtbv 8Itex6hs&ei=WK-eVZTqHtS6ogSk-42oBg&usg=AFQjCNHU-j_eLcVaxhweKeBcMT3OwRAA8g&sig2=5DGc27UbjvJzMK0kKue4Bw&bvm=bv.96952980,d.cGU)
لینک 3 (http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=8&cad=rja&uact=8&ved=0CE0QtwIwBw&url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DXT-0oUtVOpg&ei=WK-eVZTqHtS6ogSk-42oBg&usg=AFQjCNEV1Xqt_DURqy3R1B7x36HSjNIgug&sig2=vKFBxvEzblXzCO3xUyUqUw&bvm=bv.96952980,d.cGU)
موفق و پیروز باشید...

suraty
چهارشنبه 24 تیر 1394, 15:36 عصر
بی نهایت سپاسگزارم. امیدوارم در کارها و پروژه هاتون موفق باشید.
برنامه روی دو تا گوشی اجرا شد و درست عمل کرد. خیلی از راهنمایی هاتون ممنونم. شاید اینکه دفعه پیش درست نشد، به مدل گوشی هم ربط داشته!
من وضعیت وای فای رو دستی تغییر دادم و امتحان کردم، حالا میشه این کار بدون دخالت کاربر انجام بشه؟ یعنی با کدنویسی اینتنت WIFI_P2P_STATE_CHANGED_ACTION منتشر بشه؟
همه چیز خوب بود تا اینکه با سه تا گوشی اجرا گرفتیم! سرور گوشی های اطراف رو پیدا کرد، اما نشد که فایل عکس ارسال بشه!! یعنی باز هم موقع اجرا اشتباهی کردم؟ یا اینکه بالای دو گوشی رو جواب نمیده؟
بابت لینک هایی که گذاشتید هم بسیار ممنونم.

eshtiyaghi90
شنبه 30 مرداد 1395, 15:06 عصر
سلام
اگه امکانش هست سورس برنامه ای که جواب داده رو هم بزارید.
ممنون