Подтвердить что ты не робот

Как распечатать текстовый файл с помощью WiFi Direct

У меня есть приложение для Android, которое отображает статистику пользователя. Я хочу отправить небольшой отчет с текстовым форматом (.txt) на принтер WiFi Direct. Я загрузил образец приложения demo из Android. Я сделал правильную модификацию, чтобы искать .txt файл. Но я не понимаю, почему мой код не работает. После выбора файла, который я хочу распечатать, ничего не происходит.

Текущая конфигурация для моего принтера EPSON ниже.

  • Wi-Fi Direct Mode: On

  • Режим связи: AP

  • Режим работы: IEEE802.11g/n

  • Скорость связи: Авто

  • SSID: DIRECT-D3A36C54
  • Канал: 7
  • Уровень безопасности: WPA2-PSK (AES)

  • Статус ссылки: Неизвестно

Это класс DeviceDetailFragment

public class DeviceDetailFragment extends Fragment implements WifiP2pManager.ConnectionInfoListener {
    protected static final int CHOOSE_FILE_RESULT_CODE = 20;
    private View mContentView = null;
    private WifiP2pDevice device;
    private WifiP2pInfo info;
    ProgressDialog progressDialog = null;
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mContentView = inflater.inflate(R.layout.device_detail, null);
        mContentView.findViewById(R.id.btn_connect).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                WifiP2pConfig config = new WifiP2pConfig();
                config.deviceAddress = device.deviceAddress;
                config.wps.setup = WpsInfo.LABEL;
                config.wps.pin = "12345677";
//                config.groupOwnerIntent = 15;
                if (progressDialog != null && progressDialog.isShowing()) {
                    progressDialog.dismiss();
                }
                progressDialog = ProgressDialog.show(getActivity(), "Press back to cancel",
                        "Connecting to :" + device.deviceAddress, true, true
//                        new DialogInterface.OnCancelListener() {
//
//                            @Override
//                            public void onCancel(DialogInterface dialog) {
//                                ((DeviceActionListener) getActivity()).cancelDisconnect();
//                            }
//                        }
                );
                ((DeviceListFragment.DeviceActionListener) getActivity()).connect(config);
            }
        });
        mContentView.findViewById(R.id.btn_disconnect).setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        ((DeviceListFragment.DeviceActionListener) getActivity()).disconnect();
                    }
                });
        mContentView.findViewById(R.id.btn_start_client).setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        // Allow user to pick a text file from storage or other
                        // registered apps
                        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                        intent.setType("text/*");
//                        intent.setType("image/*");
                        startActivityForResult(intent, CHOOSE_FILE_RESULT_CODE);
                    }
                });
        return mContentView;
    }
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        // User has picked a text file. Transfer it to group owner i.e peer using
        // FileTransferService.
        Uri uri = data.getData();
        TextView statusText = (TextView) mContentView.findViewById(R.id.status_text);
        statusText.setText("Sending: " + uri);
        Log.d(WiFiDirectActivity.TAG, "Intent----------- " + uri);
        Intent serviceIntent = new Intent(getActivity(), FileTransferService.class);
        serviceIntent.setAction(FileTransferService.ACTION_SEND_FILE);
        serviceIntent.putExtra(FileTransferService.EXTRAS_FILE_PATH, uri.toString());
        serviceIntent.putExtra(FileTransferService.EXTRAS_GROUP_OWNER_ADDRESS,
                info.groupOwnerAddress.getHostAddress());
        serviceIntent.putExtra(FileTransferService.EXTRAS_GROUP_OWNER_PORT, 8315); //631
        getActivity().startService(serviceIntent);
    }
    @Override
    public void onConnectionInfoAvailable(final WifiP2pInfo info) {
        if (progressDialog != null && progressDialog.isShowing()) {
            progressDialog.dismiss();
        }
        this.info = info;
        this.getView().setVisibility(View.VISIBLE);
        // The owner IP is now known.
        TextView view = (TextView) mContentView.findViewById(R.id.group_owner);
        view.setText(getResources().getString(R.string.group_owner_text)
                + ((info.isGroupOwner == true) ? getResources().getString(R.string.yes)
                : getResources().getString(R.string.no)));
        // InetAddress from WifiP2pInfo struct.
        view = (TextView) mContentView.findViewById(R.id.device_info);
        view.setText("Group Owner IP - " + info.groupOwnerAddress.getHostAddress());
        // After the group negotiation, we assign the group owner as the file
        // server. The file server is single threaded, single connection server
        // socket.
        if (info.groupFormed && info.isGroupOwner) {
            new FileServerAsyncTask(getActivity(), mContentView.findViewById(R.id.status_text))
                    .execute();
        } else if (info.groupFormed) {
            // The other device acts as the client. In this case, we enable the
            // get file button.
            mContentView.findViewById(R.id.btn_start_client).setVisibility(View.VISIBLE);
            ((TextView) mContentView.findViewById(R.id.status_text)).setText(getResources()
                    .getString(R.string.client_text));
        }
        // hide the connect button
        mContentView.findViewById(R.id.btn_connect).setVisibility(View.GONE);
    }
    /**
     * Updates the UI with device data
     *
     * @param device the device to be displayed
     */
    public void showDetails(WifiP2pDevice device) {
        this.device = device;
        this.getView().setVisibility(View.VISIBLE);
        TextView view = (TextView) mContentView.findViewById(R.id.device_address);
        view.setText(device.deviceAddress);
        view = (TextView) mContentView.findViewById(R.id.device_info);
        view.setText(device.toString());
    }
    /**
     * Clears the UI fields after a disconnect or direct mode disable operation.
     */
    public void resetViews() {
        mContentView.findViewById(R.id.btn_connect).setVisibility(View.VISIBLE);
        TextView view = (TextView) mContentView.findViewById(R.id.device_address);
        view.setText(R.string.empty);
        view = (TextView) mContentView.findViewById(R.id.device_info);
        view.setText(R.string.empty);
        view = (TextView) mContentView.findViewById(R.id.group_owner);
        view.setText(R.string.empty);
        view = (TextView) mContentView.findViewById(R.id.status_text);
        view.setText(R.string.empty);
        mContentView.findViewById(R.id.btn_start_client).setVisibility(View.GONE);
        this.getView().setVisibility(View.GONE);
    }
    /**
     * A simple server socket that accepts connection and writes some data on
     * the stream.
     */
    public static class FileServerAsyncTask extends AsyncTask<Void, Void, String> {
        private Context context;
        private TextView statusText;
        /**
         * @param context
         * @param statusText
         */
        public FileServerAsyncTask(Context context, View statusText) {
            this.context = context;
            this.statusText = (TextView) statusText;
        }
        @Override
        protected String doInBackground(Void... params) {
            try {
                ServerSocket serverSocket = new ServerSocket(8315); //631
                Log.d(WiFiDirectActivity.TAG, "Server: Socket opened");
                Socket client = serverSocket.accept();

                Log.d(WiFiDirectActivity.TAG, "Server: connection done");
//                final File f = new File(Environment.getExternalStorageDirectory() + "/"
//                        + context.getPackageName() + "/wifip2pshared-" + System.currentTimeMillis()
//                        + ".txt");


                final File f = new File(Environment.getExternalStorageDirectory() + "/"
                        + context.getPackageName() + "/wifip2pshared-" + ".txt");
                File dirs = new File(f.getParent());
                if (!dirs.exists())
                    dirs.mkdirs();
                f.createNewFile();
                Log.d(WiFiDirectActivity.TAG, "server: copying files " + f.toString());
                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;
            }
        }
        /*
         * (non-Javadoc)
         * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
         */
        @Override
        protected void onPostExecute(String result) {
            if (result != null) {
                statusText.setText("File copied - " + result);
//                Log.e("...File copied - ", result);
                Intent intent = new Intent();
                intent.setAction(android.content.Intent.ACTION_VIEW);
                intent.setDataAndType(Uri.parse("file://" + result), "text/*");
                context.startActivity(intent);
            } else {
                Log.e("File copied is NULL- ", result);
            }
        }
        /*
         * (non-Javadoc)
         * @see android.os.AsyncTask#onPreExecute()
         */
        @Override
        protected void onPreExecute() {
            statusText.setText("Opening a server socket");
        }
    }
    public static boolean copyFile(InputStream inputStream, OutputStream out) {
        byte buf[] = new byte[1024];
        int len;
        try {
            while ((len = inputStream.read(buf)) != -1) {
                out.write(buf, 0, len);
            }
            out.close();
            inputStream.close();
        } catch (IOException e) {
            Log.d(WiFiDirectActivity.TAG, e.toString());
            return false;
        }
        return true;
    }
}

РЕДАКТИРОВАТЬ № 1 Это моя настройка разрешений

<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.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.BIND_PRINT_SERVICE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

После подключения к принтеру у меня есть пользовательский интерфейс для выбора файла, после того как я его выберу, ничего не происходит, я просто получил приведенный ниже вывод консоли (файл, который я собираю, находится на SD-карте)

  • 05-17 10: 39: 50.994 28659-28659/com.example.ccano.wifidirect E/ViewRootImpl: sendUserActionEvent() mView == null

  • 05-17 10: 39: 52.314 28659-28659/com.example.ccano.wifidirect D/ViewRootImpl: ViewPostImeInputStage processPointer 0

  • 05-17 10: 39: 52.384 28659-28659/com.example.ccano.wifidirect D/ViewRootImpl: ViewPostImeInputStage processPointer 1

  • 05-17 10: 39: 56.484 28659-28659/com.example.ccano.wifidirect D/wifidirectdemo: намерение -----------
    Содержание://com.android.externalstorage.documents/document/9C33-6BBD%3Asample_file.txt

  • 05-17 10: 39: 56.514 28659-28659/com.example.ccano.wifidirect D/wifidirectdemo: состояние P2P изменено - 2

  • 05-17 10: 39: 56.514 28659-29309/com.example.ccano.wifidirect D/wifidirectdemo: Открытие клиентского сокета -

  • 05-17 10: 39: 56.514 28659-28659/com.example.ccano.wifidirect D/wifidirectdemo: Состояние равноправия: 0

  • 05-17 10: 39: 56.524 28659-29309/com.example.ccano.wifidirect D/wifidirectdemo: Клиентский сокет - true
  • 05-17 10: 39: 56.524 28659-29309/com.example.ccano.wifidirect E/ccano..copyfile: true

  • 05-17 10: 39: 56.524 28659-29309/com.example.ccano.wifidirect D/wifidirectdemo: Клиент: записанные данные

  • 05-17 10: 39: 56.534 28659-28659/com.example.ccano.wifidirect I/Хронология: Сроки: Идентификатор Activity_idle:
    [email protected] время: 4602644
  • 05-17 10: 41: 01.714 28659-28659/com.example.ccano.wifidirect D/ViewRootImpl: ViewPostImeInputStage processPointer 0
  • 05-17 10: 41: 01.774 28659-28659/com.example.ccano.wifidirect D/ViewRootImpl: ViewPostImeInputStage processPointer 1
  • 05-17 10: 41: 02.564 28659-28659/com.example.ccano.wifidirect D/wifidirectdemo: обмены P2P изменены
  • 05-17 10: 41: 02.574 28659-28659/com.example.ccano.wifidirect D/wifidirectdemo: Статус партнера: 3
  • 05-17 10: 41: 02.594 28659-28659/com.example.ccano.wifidirect D/wifidirectdemo: устройств не найдено.

РЕДАКТИРОВАТЬ № 2

После добавления нижней строки в мой манифест, я все равно получаю такой же результат, ничего не происходит.

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

введите описание изображения здесь

Изменить # 3

Теперь, после изменения WpsInfo.Label на WpsInfo.PBC, я получаю другой вывод на консоли отладчика. (см. снимок экрана ниже). Но, по-прежнему, принтер не отправляет задание на печать.

введите описание изображения здесь

4b9b3361

Ответ 1

Оказалось, что мой код был прекрасным, после нескольких дней тестирования и проведения исследований я выяснил, что проблема была в классе сокетов, я использовал стандартную версию, которую Google предоставляет в демо-коде (который является одним из Я использовал), но, прочитав официальную документацию из Wi-Fi.org, я мог понять, что номер порта имеет значение, и, чтобы заставить его работать с WiFi Direct только вам нужно настроить порт № 631, и принтер спросит вас о PIN-пароле, если он включен. Теперь, если вы хотите использовать P2P и обходя пароль, вам необходимо использовать порт # 9100.

Итак, я сделал это, используя оба порта 9100 и 631, и теперь я печатаю файлы txt.

Теперь, если вы хотите распечатать PDF, вам просто нужно добавить:

intent.setType("application/pdf"); 

и

intent.setDataAndType(Uri.parse("file://" + result), "application/pdf");

в класс DeviceDetailFragment (тот, который указан выше).

Я надеюсь, что этот пост обеспечит хорошее понимание и внутреннюю информацию о печати на Android с P2P-коммуникацией.

Ответ 2

Вы можете перейти по этой ссылке.
Об основных знаниях о Wi-Fi Direct (P2P)
https://developer.android.com/guide/topics/connectivity/wifip2p.html

https://developer.android.com/training/connect-devices-wirelessly/wifi-direct.html

https://developer.android.com/training/connect-devices-wirelessly/nsd-wifi-direct.html

 здесь 3 проекта с открытым исходным кодом (с открытым исходным кодом).
https://fossdroid.com/s.html?q=+printer

здесь 3 демонстрационных приложения с исходными кодами:
https://github.com/SureshCS-50/Android-wifi-print

Bluetooth и печать WIFI для Android

и https://trivedihardik.wordpress.com/2012/08/31/android-wifi-direct-example/


Он будет работать на 100%.
Файл Manifext:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.waltonbd.printerfinal">
    <uses-permission android:name="android.permission.INTERNET"></uses-permission>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

Файл MainActivity.Java

import android.content.Context;
import android.os.Bundle;
import android.os.StrictMode;
import android.support.v7.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.Toast;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class MainActivity extends AppCompatActivity {
public Context mContext;
    public EditText edIP,edPort,edPrint;
    // "192.168.134.159"
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
        mContext=this;
        edIP=(EditText)findViewById(R.id.edIP);
        edPort=(EditText)findViewById(R.id.edPort);
        edPrint=(EditText)findViewById(R.id.edPrint);
        edIP.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View view, MotionEvent motionEvent) {
                // your code here....

                getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);

                return false;
            }
        });
    }
    public void printAction(View v)
    {
       if(!edIP.getText().toString().equals("") && !edPort.getText().toString().equals("") && !edPrint.getText().toString().equals(""))
       {
           if(CheckInternet.checkConn(mContext))
           {
               printPart();

           }
           else
           {
               Toast.makeText(mContext,"First of all, Check your internet connection,Please",Toast.LENGTH_LONG).show();
           }
       }
        else
       {
           Toast.makeText(mContext,"Please fill up all fields",Toast.LENGTH_LONG).show();
       }
    }
    public void printPart()
    {
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();

        StrictMode.setThreadPolicy(policy);
        try {
            String ip=edIP.getText().toString();
            int port= Integer.valueOf(edPort.getText().toString());
            String printMsg=edPrint.getText().toString();
            Socket sock = new Socket(ip,port);
            PrintWriter oStream = new PrintWriter(sock.getOutputStream());
           // oStream.println("HI,test from Android Device");
            oStream.println(printMsg);

            oStream.println("\n\n\n");
            oStream.println(new char[]{0x1D, 0x56, 0x41, 0x10});
            oStream.close();
            sock.close();
            edPrint.setText("");
            Toast.makeText(mContext,"Please, Receive your print copy",Toast.LENGTH_LONG).show();
        }
        catch (UnknownHostException e)
        {
            e.printStackTrace();
            Toast.makeText(MainActivity.this,"UnknownHostException:"+e.toString(),Toast.LENGTH_LONG).show();
        }
        catch (IOException e)
        {
            e.printStackTrace();
            Toast.makeText(MainActivity.this,"IOException:"+e.toString(),Toast.LENGTH_LONG).show();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
    }
}

Файл CheckInternet.java:

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;

public class CheckInternet
{
    public static boolean checkConn(Context ctx)
    {
        ConnectivityManager conMgr = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = conMgr.getActiveNetworkInfo();
        if (info == null)
            return false;
        if (!info.isConnected())
            return false;
        if (!info.isAvailable())
            return false;
        return true;


    }


}

Файл activity_main.xml:

<?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:layout_weight="1"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:layout_weight="1"
        android:orientation="horizontal">

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="IP:" />

        <EditText
            android:id="@+id/edIP"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="3"
            android:hint="192.168.0.0" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:layout_weight="1"
        android:orientation="horizontal">

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Port:" />

        <EditText
            android:id="@+id/edPort"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="3"
            android:hint="9100" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:layout_weight="7"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Print Input:" />


        <EditText
            android:id="@+id/edPrint"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:gravity="top|left"
            android:inputType="textMultiLine"
            android:lines="10"
            android:hint="type your print data here"
            android:maxLines="100"
            android:minLines="10"
            android:scrollbars="vertical" />
    </LinearLayout>


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1">

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="50dp"
            android:onClick="printAction"
            android:text="Print" />
    </LinearLayout>

</LinearLayout>