/* Copyright (C) 2014 Sergii Pylypenko. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.cups.android; import android.app.Activity; import android.app.Service; import android.content.Context; import android.os.Bundle; import android.os.IBinder; import android.view.MotionEvent; import android.view.KeyEvent; import android.view.Window; import android.view.WindowManager; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import android.widget.EditText; import android.text.Editable; import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.FrameLayout; import android.graphics.drawable.Drawable; import android.graphics.Color; import android.content.res.Configuration; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Intent; import android.view.View.OnKeyListener; import android.view.MenuItem; import android.view.Menu; import android.view.Gravity; import android.text.method.TextKeyListener; import java.util.LinkedList; import java.io.SequenceInputStream; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.FileOutputStream; import java.io.File; import java.io.FileInputStream; import java.util.Set; import android.text.SpannedString; import java.io.BufferedReader; import java.io.BufferedInputStream; import java.io.InputStreamReader; import android.view.inputmethod.InputMethodManager; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Handler; import android.os.Message; import android.os.SystemClock; import java.util.concurrent.Semaphore; import android.content.pm.ActivityInfo; import android.view.Display; import android.text.InputType; import android.util.Log; import android.view.Surface; import android.app.ProgressDialog; import android.text.util.Linkify; import android.widget.ScrollView; import java.util.*; import android.text.TextWatcher; import android.app.AlertDialog; import android.content.DialogInterface; import android.app.ProgressDialog; import android.text.method.PasswordTransformationMethod; import android.widget.Toast; import android.widget.CheckBox; import android.widget.CompoundButton; import android.view.Gravity; import android.net.Uri; public class AddPrinterActivity extends Activity { private ScrollView scroll = null; private LinearLayout layout = null; private Button viewNetwork = null; private EditText name = null; private EditText server = null; private EditText printer = null; private EditText model = null; private Button selectModel = null; private EditText domain = null; private EditText user = null; private EditText password = null; private Button addPrinter = null; private ProgressDialog progressCircle = null; private Map<String, String> modelList = null; private String[] networkTree = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, "onCreate"); scroll = new ScrollView(this); setContentView(scroll); getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); layout = new LinearLayout(this); layout.setOrientation(LinearLayout.VERTICAL); layout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); layout.setPadding(10, 10, 10, 10); scroll.addView(layout, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); viewNetwork = new Button(this); viewNetwork.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); viewNetwork.setText(getResources().getString(R.string.view_network_button)); viewNetwork.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { final String[] networkTreeCopy = networkTree; AlertDialog.Builder builder = new AlertDialog.Builder(AddPrinterActivity.this); //builder.setTitle(R.string.network); builder.setItems(networkTreeCopy, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, final int which) { dialog.dismiss(); String selected = networkTreeCopy[which]; selected = selected.trim(); if (!selected.startsWith("\\\\")) return; selected = selected.substring(2); if (selected.indexOf("\\") == -1) return; String server = selected.substring(0, selected.indexOf("\\")); String share = selected.substring(selected.indexOf("\\") + 1); share = share.split("\\s+")[0]; AddPrinterActivity.this.server.setText(server); AddPrinterActivity.this.printer.setText(share); AddPrinterActivity.this.name.setText(server + "-" + share); String workgroup = ""; for (int i = 0; i < which; i++) { if (networkTreeCopy[i].indexOf("\\") == -1) workgroup = networkTreeCopy[i]; } if (workgroup.length() > 0) AddPrinterActivity.this.domain.setText(workgroup); } }); builder.setNegativeButton(R.string.close, new DialogInterface.OnClickListener() { public void onClick(DialogInterface d, int s) { d.dismiss(); if (user.getText().toString().length() == 0 || password.getText().toString().length() == 0) Toast.makeText(AddPrinterActivity.this, R.string.login_password_hint, Toast.LENGTH_LONG).show(); } }); builder.setPositiveButton(R.string.view_network_button_scan_again, new DialogInterface.OnClickListener() { public void onClick(DialogInterface d, int s) { d.dismiss(); updateNetworkTree(); if (user.getText().toString().length() == 0 || password.getText().toString().length() == 0) Toast.makeText(AddPrinterActivity.this, R.string.login_password_hint, Toast.LENGTH_LONG).show(); } }); AlertDialog alert = builder.create(); alert.setOwnerActivity(AddPrinterActivity.this); alert.show(); } }); layout.addView(viewNetwork); TextView text = null; text = new TextView(this); text.setText(R.string.name_desc); text.setTextSize(20); layout.addView(text); name = new EditText(this); name.setHint(R.string.name_hint); name.setInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); layout.addView(name); text = new TextView(this); text.setText(R.string.server_desc); text.setTextSize(20); layout.addView(text); server = new EditText(this); server.setHint(R.string.server_hint); server.setInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); layout.addView(server); text = new TextView(this); text.setText(R.string.printer_desc); text.setTextSize(20); layout.addView(text); printer = new EditText(this); printer.setHint(R.string.printer_hint); printer.setInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); layout.addView(printer); text = new TextView(this); text.setText(R.string.model_desc); text.setTextSize(20); layout.addView(text); model = new EditText(this); model.setHint(R.string.model_button_reading); model.setEnabled(false); model.setInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); model.addTextChangedListener(new TextWatcher() { public void afterTextChanged(Editable s) { if (s.length() >= 1 && modelList != null) { //selectModel.setEnabled(true); selectModel.setText(getResources().getString(R.string.model_button_search)); } else { //selectModel.setEnabled(false); selectModel.setText(getResources().getString(R.string.model_button_type)); } } public void beforeTextChanged(CharSequence s, int start, int count, int after) { } public void onTextChanged(CharSequence s, int start, int before, int count) { } }); layout.addView(model); selectModel = new Button(this); selectModel.setText(getResources().getString(R.string.model_button_reading)); selectModel.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (!model.isEnabled()) { model.setEnabled(true); model.setText(""); return; } String search = model.getText().toString().toLowerCase(); final ArrayList<CharSequence> values = new ArrayList<CharSequence>(); AlertDialog.Builder builder = new AlertDialog.Builder(AddPrinterActivity.this); builder.setTitle(R.string.select_printer_model); for (String s: modelList.keySet()) { if (s.toLowerCase().indexOf(search) != -1) { Log.d(TAG, "Found model: " + s); values.add(s); } } if (values.size() == 0) { builder.setMessage(R.string.no_models_found); builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface d, int s) { d.dismiss(); } }); } else { builder.setItems(values.toArray(new CharSequence[0]), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { model.setText(values.get(which)); model.setEnabled(false); selectModel.setText(getResources().getString(R.string.model_button_clear)); } }); } AlertDialog alert = builder.create(); alert.setOwnerActivity(AddPrinterActivity.this); alert.show(); } }); selectModel.setEnabled(false); layout.addView(selectModel); text = new TextView(this); text.setText(R.string.domain_desc); text.setTextSize(20); layout.addView(text); domain = new EditText(this); domain.setHint(R.string.domain_hint); domain.setInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); layout.addView(domain); text = new TextView(this); text.setText(R.string.user_desc); text.setTextSize(20); layout.addView(text); user = new EditText(this); user.setHint(R.string.user_hint); user.setInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); layout.addView(user); text = new TextView(this); text.setText(R.string.password_desc); text.setTextSize(20); text.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f)); CheckBox showPassword = new CheckBox(this); showPassword.setText(R.string.show_password); showPassword.setTextSize(20); showPassword.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0.0f)); showPassword.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { int selection = password.getSelectionStart(); if (isChecked) { password.setInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); password.setTransformationMethod(null); } else { password.setInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_VARIATION_PASSWORD|InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); password.setTransformationMethod(PasswordTransformationMethod.getInstance()); } password.setSelection(selection); } }); LinearLayout layout2 = new LinearLayout(this); layout2.setOrientation(LinearLayout.HORIZONTAL); layout2.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); layout2.addView(text); layout2.addView(showPassword); layout.addView(layout2); password = new EditText(this); password.setHint(R.string.password_hint); password.setInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_VARIATION_PASSWORD|InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); password.setTransformationMethod(PasswordTransformationMethod.getInstance()); layout.addView(password); text = new TextView(this); text.setText(""); layout.addView(text); addPrinter = new Button(this); addPrinter.setEnabled(false); addPrinter.setText(getResources().getString(R.string.add_printer_button) + " - " + getResources().getString(R.string.model_button_reading)); addPrinter.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (name.getText().length() == 0 || server.getText().length() == 0 || printer.getText().length() == 0 || model.isEnabled() || model.getText().length() == 0) { AlertDialog.Builder builder = new AlertDialog.Builder(AddPrinterActivity.this); builder.setTitle(R.string.error); builder.setMessage(R.string.error_empty_fields); builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface d, int s) { d.dismiss(); } }); AlertDialog alert = builder.create(); alert.setOwnerActivity(AddPrinterActivity.this); alert.show(); return; } progressCircle.show(); new Thread(new Runnable() { public void run() { Cups.addPrinter(AddPrinterActivity.this, name.getText().toString(), server.getText().toString(), printer.getText().toString(), modelList.get(model.getText().toString()), domain.getText().toString().toUpperCase(), user.getText().toString(), password.getText().toString()); Cups.updatePrintersInfo(AddPrinterActivity.this); runOnUiThread(new Runnable() { public void run() { progressCircle.dismiss(); Toast.makeText(AddPrinterActivity.this, R.string.printer_added_successfully, Toast.LENGTH_LONG).show(); finish(); } }); } }).start(); } }); layout.addView(addPrinter); progressCircle = new ProgressDialog(this); progressCircle.setMessage(getResources().getString(R.string.please_wait)); updateNetworkTree(); Uri uri = getIntent() != null ? getIntent().getData() : null; if (uri != null && uri.getScheme() != null && uri.getHost() != null && getResources().getString(R.string.add_printer_scheme).equals(uri.getScheme()) && getResources().getString(R.string.add_printer_host).equals(uri.getHost())) { name.setText(uri.getQueryParameter("n")); server.setText(uri.getQueryParameter("s")); printer.setText(uri.getQueryParameter("p")); model.setText(uri.getQueryParameter("m")); domain.setText(uri.getQueryParameter("d")); user.setText(uri.getQueryParameter("u")); password.setText(uri.getQueryParameter("pw")); } updateModelList(); } private void updateModelList() { new Thread(new Runnable() { public void run() { modelList = Cups.getPrinterModels(AddPrinterActivity.this); runOnUiThread(new Runnable() { public void run() { selectModel.setText(getResources().getString(R.string.model_button_type)); model.setHint(R.string.model_hint); if (model.getText().toString().length() > 0 && modelList.get(model.getText().toString()) == null) model.setText(""); if (model.getText().toString().length() == 0) model.setEnabled(true); else selectModel.setText(getResources().getString(R.string.model_button_clear)); selectModel.setEnabled(true); addPrinter.setEnabled(true); addPrinter.setText(getResources().getString(R.string.add_printer_button)); } }); } }).start(); } public void updateNetworkTree() { if (viewNetwork == null) return; viewNetwork.setEnabled(false); viewNetwork.setText(getResources().getString(R.string.view_network_button_scanning)); new Thread(new Runnable() { public void run() { networkTree = Cups.getNetworkTree(AddPrinterActivity.this, user.getText().toString(), password.getText().toString(), domain.getText().toString()); runOnUiThread(new Runnable() { public void run() { if (viewNetwork == null) return; viewNetwork.setEnabled(true); viewNetwork.setText(getResources().getString(R.string.view_network_button)); } }); } }).start(); } static public final String TAG = "AddPrinterActivity"; }