如何通过WiFi发布设备名称(变量),就像某些文件传输应用程序一样?

时间:2016-12-15 12:07:38

标签: java android android-wifi

我想通过WiFi发布或宣传我的设备名称,这是可变的,可由用户更改。

例如,选择文件传输应用程序Xender。当我们在应用中选择receive选项时,我们可以在屏幕上看到用户设置的设备名称。这是屏幕截图。

enter image description here

您可以在图片中看到名称shah.kaushal正在出现。

我在互联网上搜索了很多结果,但无法弄清楚究竟是什么。

我知道主机名,但我认为通常不会被这些应用程序更改,我认为它需要一些特殊权限才能在Android上执行此操作。所以我确定它不是主机名,我们可以从IP地址轻松获取。

请注意我不会复制任何其他应用功能。我希望在我的音乐播放器应用程序中共享歌曲。

为此,我在设备之间使用了TCP连接。我可以成功地将歌曲从一个设备发送到另一个设备。但它需要设备的IP地址。哪个用户不友好。

以下是我的基本音乐分享活动的屏幕截图,其中列出了可用的IP地址,用户必须从列表中选择一个IP。

enter image description here

我想显示设备名称而不是IP地址。

我发送文件的代码是:

 @Override
protected Void doInBackground(Void... voids) {


    System.out.println("array list");
    ArrayList<File> files = new ArrayList<>();
    System.out.println("about to create.");

    files.add(new File(wholePath));
    System.out.println("file created..");
    try {


        //Receiving IP addresses which are available to send our files(Music)!!
        a = getClientList();


        //update the UI to display the received IP addresses!!
        publishProgress();


        //busy waiting for user to select appropriate IP address to send files!
        while (destinationAddress.equals("-1")){

        }

        //User has selected something, It's time to send files there!
        socket = new Socket(destinationAddress,5004);

        System.out.println("Connecting...");
        DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
        System.out.println(files.size());
        //write the number of files to the server
        dos.writeInt(files.size());
        dos.flush();


        //write file size
        for(int i = 0;i< files.size();i++){
            int file_size = Integer.parseInt(String.valueOf(files.get(i).length()));
            dos.writeLong(file_size);
            dos.flush();
        }

        //write file names
        for(int i = 0 ; i < files.size();i++){
            dos.writeUTF(files.get(i).getName());
            dos.flush();
        }

        //buffer for file writing, to declare inside or outside loop?
        int n = 0;
        byte[]buf = new byte[4092];
        //outer loop, executes one for each file
        for(int i =0; i < files.size(); i++){

            System.out.println(files.get(i).getName());
            //create new fileinputstream for each file
            FileInputStream fis = new FileInputStream(files.get(i));

            //write file to dos
            while((n =fis.read(buf)) != -1){
                dos.write(buf,0,n);
                dos.flush();

            }

        }

        dos.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        xceptionFlag = true;
        e.printStackTrace();
    }

    Log.i("===end of start ====", "==");
    try{
        if(!socket.isClosed()){
            socket.close();
        }
    }
    catch (Exception e){
        xceptionFlag = true;
        e.printStackTrace();
    }

    return null;
}

接收文件的代码是:

    @Override
protected Void doInBackground(Void... voids) {


    try {


        //this is done isntead of above line because it was givind error of address is already in use.
        ss = new ServerSocket();
        ss.setReuseAddress(true);
        ss.bind(new InetSocketAddress(5004));

        System.out.println("waiting");

        Socket socket = ss.accept();
        System.out.println("Accepted!");
        DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
        //read the number of files from the client
        int number = dis.readInt();
        ArrayList<File>files = new ArrayList<File>(number);
        System.out.println("Number of Files to be received: " +number);

        ArrayList<Long> fileSize = new ArrayList<>(number);


        for(int i = 0; i < number ;i++){
            long size = dis.readLong();
            System.out.println(size);
            fileSize.add(size);
        }

        //read file names, add files to arraylist
        for(int i = 0; i< number;i++){
            File file = new File(dis.readUTF());
            files.add(file);
        }
        int n = 0;
        byte[]buf = new byte[4092];

        //outer loop, executes one for each file
        for(int i = 0; i < files.size();i++){

            System.out.println("Receiving file: " + files.get(i).getName());

            //Create new Folder for our app, if it is not there and store received files there in our separate folder.
            File folder = new File(Environment.getExternalStorageDirectory() +
                    File.separator + "File");
            boolean success = true;
            if (!folder.exists()) {
                success = folder.mkdirs();
            }
            if (success) {
                // Do something on success
            } else {
                // Do something else on failure
            }


            //create a new fileoutputstream for each new file
            FileOutputStream fos = new FileOutputStream("mnt/sdcard/File/" +files.get(i).getName());
            //read file

            while (fileSize.get(i) > 0 && (n = dis.read(buf, 0, (int)Math.min(buf.length, fileSize.get(i)))) != -1)
            {
                fos.write(buf,0,n);
                long x = fileSize.get(i);
                x = x-n;
                fileSize.set(i,x);
            }
            fos.close();
        }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        xceptionFlag = true;
        e.printStackTrace();

    }
    ////////////////////
    Log.i("== the end of read ====", "==");
    try{
        if(!ss.isClosed()){
            ss.close();
        }
    }
    catch (Exception e){
        xceptionFlag = true;
        e.printStackTrace();
    }
    return null;
}

我已将代码包含在内以供参考。感谢。

2 个答案:

答案 0 :(得分:1)

只需将名称设置并存储在SharedPreferences或任何地方作为字符串,然后当您显示列出IP的屏幕时,连接到它们中的每一个并传输此字符串并显示它而不是知识产权。像Send a string instead of byte through socket in Java这样的东西来转移字符串。

如果要从设备发布名称,请启动此服务,并在不再发布名称时停止该服务:

public class NameService extends Service {

    private volatile boolean running;
    private volatile String myName;
    private volatile ServerSocket serverSocket;

    public NameService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        try {
            serverSocket = new ServerSocket();
            serverSocket.bind(new InetSocketAddress(5006));
            serverSocket.setReuseAddress(true);
            serverSocket.setSoTimeout(2000);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        myName = PreferenceManager.getDefaultSharedPreferences(getApplicationContext())
                .getString("NAME_STRING", "TEST.NAME");
        if (!running)
        {
            running = true;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while (running)
                    {
                        try {
                            Socket socket = serverSocket.accept();
                            PrintWriter writer = new PrintWriter(new BufferedWriter(
                                    new OutputStreamWriter(socket.getOutputStream())),
                                    true);
                            writer.println(myName);

                            writer.close();
                            socket.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                    }
                }
            }).start();
        }
        return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        running = false;
        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

然后,当想要显示接收者列表时,连接到每个接收者并执行以下操作:

try {
        Socket socket = new Socket();
        socket.connect(new InetSocketAddress(ipAddress, 5006), 5000);
        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String message = reader.readLine();
        reader.close();
        socket.close();
        Log.i("TAG", message);
        } catch (IOException e) {
        e.printStackTrace();
     }

如果您想在名称运行时更改名称,可以进一步拨打startService()

我建议您使用ServiceIntentService进行文件传输,AsyncTask不合适。

答案 1 :(得分:0)

试试这个: 对于每个IP地址,您可以使用InetAddress

解析主机名
InetAddress addr = InetAddress.getByName("IP-ADDRESS");
String host = addr.getHostName();
Log.i("host:",host);

希望这会有所帮助。如果没有,我可以提出一些其他方法。