I have a working Android app that displays user stats. I want to send a small report with plain text format (.txt) to a WiFi Direct printer. I have downloaded the sample demo app from Android. I did the proper modification in order to look for .txt file. But I don't understand why my code is not working. After selecting the file I want to print, nothing happens.
The current configuration for my EPSON printer bellow.
Wi-Fi Direct Mode : On
Communication Mode: AP
Operation Mode: IEEE802.11g/n
Communication Speed: Auto
Security Level: WPA2-PSK(AES)
Link Status: Unknown
This is the DeviceDetailFragment class
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; } }
EDIT #1 This is my permission setting
<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" />
After connecting to the printer, I've got the UI to select the file, after I select it, nothing happens, I just got the below console output (the file I am picking up is located in the SD card)
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: Intent-----------
content://com.android.externalstorage.documents/document/9C33-6BBD%3Asample_file.txt05-17 10:39:56.514 28659-28659/com.example.ccano.wifidirect D/wifidirectdemo: P2P state changed - 2
05-17 10:39:56.514 28659-29309/com.example.ccano.wifidirect D/wifidirectdemo: Opening client socket -
05-17 10:39:56.514 28659-28659/com.example.ccano.wifidirect D/wifidirectdemo: Peer status :0
- 05-17 10:39:56.524 28659-29309/com.example.ccano.wifidirect D/wifidirectdemo: Client socket - 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: Client: Data written
- 05-17 10:39:56.534 28659-28659/com.example.ccano.wifidirect I/Timeline: Timeline: Activity_idle id:
android.os.BinderProxy@75dd5e time: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 peers changed
- 05-17 10:41:02.574 28659-28659/com.example.ccano.wifidirect D/wifidirectdemo: Peer status :3
- 05-17 10:41:02.594 28659-28659/com.example.ccano.wifidirect D/wifidirectdemo: No devices found
EDIT #2
After adding the below line into my manifiest, still I am getting same result, nothing happens.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Edit #3
After changing WpsInfo.Label to WpsInfo.PBC now, I am getting a different output on the debugger console. (see screen shot below). But, still I the printer is not sending the print job.
Is there any way to print the original txt file by the browser? Printers cannot print plaintext files. Files containing text must first undergo a rasterization process (in which the text data is set into a specific font, amongst other things) before they can be physically printed.
It turned out that my code was fine, after several days of testing and doing research, I found out that the issue was the socket class, I was using the default one that Google provides in the demo code (which is the one I was using) but, after reading the official documentation from Wi-Fi.org I could understand that port number matters and, in order to make it work with WiFi Direct only you have to target port #631 and the printer will ask you about the PIN password in case that it is enabled. Now, if you want to use P2P and by-passing the password, you have to use the port #9100.
So, I did it using both ports 9100 and 631 and now I am printing txt files.
Now, if you want to print PDF, you just need to add:
intent.setType("application/pdf");
and
intent.setDataAndType(Uri.parse("file://" + result), "application/pdf");
to the DeviceDetailFragment class (the one is posted above).
I hope this post will provide a good understanding and inside about Android printing with P2P communication.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With