getCurrentInputConnection is always null - android

I try to inject some keys in a text field with a InputMethodService.
In my Manifest everything seems alright.
Everytime when I call getCurrentInputConnection() I get null.
My class extends InputMethodService and I start the service.
Can anyone help me? Is there something else I need to do to get the currentInputConnection??
Here is the code:
Its from an open source project called WifiKeyboard
And I try to inject code with the function setText(String text)
package com.example.twolibs;
/**
* WiFi Keyboard - Remote Keyboard for Android.
* Copyright (C) 2011 Ivan Volosyuk
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import java.util.HashSet;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.hardware.input.InputManager;
import android.inputmethodservice.InputMethodService;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.RemoteException;
import android.text.InputType;
import android.util.Log;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethod;
public class WiFiInputMethod extends InputMethodService {
public static final int KEY_HOME = -1000;
public static final int KEY_END = -1001;
public static final int KEY_CONTROL = -1002;
public static final int KEY_DEL = -1003;
#Override
public void onStartInput(EditorInfo attribute, boolean restarting) {
super.onStartInput(attribute, restarting);
// boolean multiline = (attribute.inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) != 0;
// Log.d("ivan", "onStartInput "
// + "actionId=" + attribute.actionId + " "
// + "id=" + attribute.fieldId + " "
// + "name=" + attribute.fieldName + " "
// + "opt=" + Integer.toHexString(attribute.imeOptions) + " "
// + "inputType=" + Integer.toHexString(attribute.inputType) + " "
// + "priv=" + attribute.privateImeOptions
// + "multiline=" + multiline);
try {
String text = getText();
} catch (NullPointerException e) {
}
}
ServiceConnection serviceConnection;
#Override
public void onDestroy() {
// Debug.d("WiFiInputMethod onDestroy()");
if (serviceConnection != null)
unbindService(serviceConnection);
serviceConnection = null;
super.onDestroy();
}
PowerManager.WakeLock wakeLock;
HashSet<Integer> pressedKeys = new HashSet<Integer>();
#Override
public void onCreate() {
super.onCreate();
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(
PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, "wifikeyboard");
// Debug.d("WiFiInputMethod started");
serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
// Debug.d("WiFiInputMethod connected to HttpService.");
}
//#Override
public void onServiceDisconnected(ComponentName name) {
// Debug.d("WiFiInputMethod disconnected from HttpService.");
}
};
}
#Override
public boolean onEvaluateFullscreenMode() {
return false;
}
void receivedChar(int code) {
wakeLock.acquire();
wakeLock.release();
InputConnection conn = getCurrentInputConnection();
if (conn == null) {
// Debug.d("connection closed");
return;
}
if (pressedKeys.contains(KEY_CONTROL)) {
switch (code) {
case 'a':case 'A': selectAll(conn); return;
case 'x':case 'X': cut(conn); return;
case 'c':case 'C': copy(conn); return;
case 'v':case 'V': paste(conn); return;
}
}
String text = null;
if (code >= 0 && code <= 65535) {
text = new String(new char[] { (char) code } );
} else {
int HI_SURROGATE_START = 0xD800;
int LO_SURROGATE_START = 0xDC00;
int hi = ((code >> 10) & 0x3FF) - 0x040 | HI_SURROGATE_START;
int lo = LO_SURROGATE_START | (code & 0x3FF);
text = new String(new char[] { (char) hi, (char) lo } );
}
conn.commitText(text, 1);
}
#SuppressWarnings("unused")
void receivedKey(int code, boolean pressed) {
if (false) {
for (int key : pressedKeys) {
sendKey(key, false, false);
}
pressedKeys.clear();
resetModifiers();
return;
}
if (pressedKeys.contains(code) == pressed) {
if (pressed == false) return;
// ignore autorepeat on following keys
switch (code) {
case KeyEvent.KEYCODE_ALT_LEFT:
case KeyEvent.KEYCODE_SHIFT_LEFT:
case KeyEvent.KEYCODE_HOME:
case KeyEvent.KEYCODE_MENU: return;
}
}
if (pressed) {
pressedKeys.add(code);
System.out.println("one");
sendKey(code, pressed, false);
} else {
pressedKeys.remove(code);
sendKey(code, pressed, pressedKeys.isEmpty());
}
}
void resetModifiers() {
InputConnection conn = getCurrentInputConnection();
if (conn == null) {
return;
}
conn.clearMetaKeyStates(
KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON);
}
private long lastWake;
void sendKey(int code, boolean down, boolean resetModifiers) {
System.out.println("two");
/*
long time = System.currentTimeMillis();
if (time - lastWake > 5000) {
wakeLock.acquire();
wakeLock.release();
lastWake = time;
}
*/
InputConnection conn = getCurrentInputConnection();
System.out.println("three");
if (conn == null) {
System.out.println("kacke");
// Debug.d("connection closed");
return;
}
if (code < 0) {
if (down == false) return;
switch (code) {
case KEY_HOME: keyHome(conn); break;
case KEY_END: keyEnd(conn); break;
case KEY_DEL: keyDel(conn); break;
}
return;
}
if (pressedKeys.contains(KEY_CONTROL)) {
switch (code) {
case KeyEvent.KEYCODE_DPAD_LEFT:
if (!down) return;
wordLeft(conn);
return;
case KeyEvent.KEYCODE_DPAD_RIGHT:
if (!down) return;
wordRight(conn);
return;
case KeyEvent.KEYCODE_DEL:
if (!down) return;
deleteWordLeft(conn);
return;
case KeyEvent.KEYCODE_FORWARD_DEL:
deleteWordRight(conn);
return;
case KeyEvent.KEYCODE_DPAD_CENTER:
if (!down) return;
copy(conn);
return;
}
}
if (pressedKeys.contains(KeyEvent.KEYCODE_SHIFT_LEFT)) {
switch (code) {
case KeyEvent.KEYCODE_DPAD_CENTER:
if (!down) return;
paste(conn);
return;
}
}
if (code == KeyEvent.KEYCODE_ENTER) {
if (shouldSend()) {
if (!down) return;
Log.d("ivan", "sending submit action");
conn.performEditorAction(EditorInfo.IME_ACTION_SEND);
return;
}
}
// if (pressedKeys.contains(KEY_CONTROL)) {
// if (down == false) return;
// switch (code) {
// case KeyEvent.KEYCODE_A: selectAll(conn); break;
// case KeyEvent.KEYCODE_X: cut(conn); break;
// case KeyEvent.KEYCODE_C: copy(conn); break;
// case KeyEvent.KEYCODE_V: paste(conn); break;
// }
// return;
// }
System.out.println("four");
conn.sendKeyEvent(new KeyEvent(
android.os.SystemClock.uptimeMillis(),
android.os.SystemClock.uptimeMillis(),
down ? KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP,
code,
0,
(pressedKeys.contains(KeyEvent.KEYCODE_SHIFT_LEFT)
? KeyEvent.META_SHIFT_LEFT_ON : 0) +
(pressedKeys.contains(KEY_CONTROL)? KeyEvent.META_CTRL_ON : 0) +
(pressedKeys.contains(KeyEvent.KEYCODE_ALT_LEFT)
? KeyEvent.META_ALT_LEFT_ON : 0)
));
if (resetModifiers) {
conn.clearMetaKeyStates(
KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON);
}
}
private boolean shouldSend() {
if (pressedKeys.contains(KEY_CONTROL)) {
// Log.d("ivan", "Control pressed");
return true;
}
EditorInfo editorInfo = getCurrentInputEditorInfo();
if (editorInfo == null) {
// Log.d("ivan", "No editor info");
return false;
}
if ((editorInfo.inputType & InputType.TYPE_CLASS_TEXT) == 0) {
// Log.d("ivan", "Not text, sending enter");
return false;
}
if ((editorInfo.inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) != 0) {
// Log.d("ivan", "Multi-line, sending ordinary enter");
return false;
}
int action = editorInfo.imeOptions & EditorInfo.IME_MASK_ACTION;
if (action == EditorInfo.IME_ACTION_NONE || action == EditorInfo.IME_ACTION_DONE) {
// Log.d("ivan", "No useful action, sending enter");
return false;
}
// Log.d("ivan", "Useful action to be performed");
return true;
}
private void keyDel(InputConnection conn) {
// if control key used -- delete word right
if (pressedKeys.contains(KEY_CONTROL)) {
deleteWordRight(conn);
return;
}
if (pressedKeys.contains(KeyEvent.KEYCODE_SHIFT_LEFT)) {
cut(conn);
return;
}
conn.deleteSurroundingText(0, 1);
conn.commitText("", 0);
}
private void paste(InputConnection conn) {
conn.performContextMenuAction(android.R.id.paste);
}
private void copy(InputConnection conn) {
conn.performContextMenuAction(android.R.id.copy);
}
private void cut(InputConnection conn) {
conn.performContextMenuAction(android.R.id.cut);
}
public void selectAll(InputConnection conn) {
ExtractedText text = conn.getExtractedText(req, 0);
try {
conn.setSelection(0, text.text.length());
} catch (NullPointerException e) {
// Potentially, text or text.text can be null
}
}
ExtractedTextRequest req = new ExtractedTextRequest();
{
req.hintMaxChars = 100000;
req.hintMaxLines = 10000;
}
private void deleteWordRight(InputConnection conn) {
ExtractedText text = conn.getExtractedText(req, 0);
if (text == null) return;
int end = text.selectionEnd;
String str = text.text.toString();
int len = str.length();
for (; end < len; end++) {
if (!Character.isSpace(str.charAt(end))) break;
}
for (; end < len; end++) {
if (Character.isSpace(str.charAt(end))) break;
}
conn.deleteSurroundingText(0, end - text.selectionEnd);
}
private void deleteWordLeft(InputConnection conn) {
// TODO: what is the correct word deleting policy?
// delete until next space? until next different character type?
ExtractedText text = conn.getExtractedText(req, 0);
if (text == null) return;
int end = text.selectionEnd - 1;
String str = text.text.toString();
for (; end >= 0; end--) {
if (!Character.isSpace(str.charAt(end))) break;
}
for (; end >= 0; end--) {
if (Character.isSpace(str.charAt(end))) break;
}
end++;
conn.deleteSurroundingText(text.selectionEnd - end, 0);
}
private void wordRight(InputConnection conn) {
boolean shift = pressedKeys.contains(KeyEvent.KEYCODE_SHIFT_LEFT);
ExtractedText text = conn.getExtractedText(req, 0);
if (text == null) return;
int end = text.selectionEnd;
String str = text.text.toString();
int len = str.length();
for (; end < len; end++) {
if (!Character.isSpace(str.charAt(end))) break;
}
for (; end < len; end++) {
if (Character.isSpace(str.charAt(end))) break;
}
int start = shift ? text.selectionStart : end;
Log.d("wifikeyboard", "start = " + start + " end = " + end);
conn.setSelection(start, end);
}
private void wordLeft(InputConnection conn) {
boolean shift = pressedKeys.contains(KeyEvent.KEYCODE_SHIFT_LEFT);
ExtractedText text = conn.getExtractedText(req, 0);
if (text == null) return;
int end = text.selectionEnd - 1;
String str = text.text.toString();
for (; end >= 0; end--) {
if (!Character.isSpace(str.charAt(end))) break;
}
for (; end >= 0; end--) {
if (Character.isSpace(str.charAt(end))) break;
}
end++;
int start = shift ? text.selectionStart : end;
Log.d("wifikeyboard", "start = " + start + " end = " + end);
conn.setSelection(start, end);
}
private void keyEnd(InputConnection conn) {
boolean control = pressedKeys.contains(KEY_CONTROL);
boolean shift = pressedKeys.contains(KeyEvent.KEYCODE_SHIFT_LEFT);
ExtractedText text = conn.getExtractedText(req, 0);
if (text == null) return;
int end;
if (control) {
end = text.text.length();
} else {
end = text.text.toString().indexOf('\n', text.selectionEnd);
if (end == -1) end = text.text.length();
}
int start = shift ? text.selectionStart : end;
Log.d("wifikeyboard", "start = " + start + " end = " + end);
conn.setSelection(start, end);
}
private void keyHome(InputConnection conn) {
boolean control = pressedKeys.contains(KEY_CONTROL);
boolean shift = pressedKeys.contains(KeyEvent.KEYCODE_SHIFT_LEFT);
ExtractedText text = conn.getExtractedText(req, 0);
if (text == null) return;
int end;
if (control) {
end = 0;
} else {
end = text.text.toString().lastIndexOf('\n', text.selectionEnd - 1);
end++;
}
int start = shift ? text.selectionStart : end;
Log.d("wifikeyboard", "start = " + start + " end = " + end);
conn.setSelection(start, end);
}
boolean setText(String text) {
// FIXME: need feedback if the input was lost
InputConnection conn = getCurrentInputConnection();
if (conn == null) {
// Debug.d("connection closed");
return false;
}
conn.commitText(text, text.length());
conn.beginBatchEdit();
// FIXME: hack
conn.deleteSurroundingText(100000, 100000);
conn.commitText(text, text.length());
conn.endBatchEdit();
return true;
}
String getText() {
String text = "";
try {
InputConnection conn = getCurrentInputConnection();
ExtractedTextRequest req = new ExtractedTextRequest();
req.hintMaxChars = 1000000;
req.hintMaxLines = 10000;
req.flags = 0;
req.token = 1;
text = conn.getExtractedText(req, 0).text.toString();
} catch (Throwable t) {
}
return text;
}
}
Thank you

Related

Masked EditText with format (XXX) XXX-XXXX ext.XXXXXX in android?

How can I mask EditText with below format in android ?
(XXX) XXX-XXXX ext.XXXXXX i.e (654) 321-5846 ext.654321
Used below Custom Edit Text class
package com.test.PhoneNumberFormatter;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v7.widget.AppCompatEditText;
import android.text.Editable;
import android.text.SpannableStringBuilder;
import android.text.TextWatcher;
import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.TextView;
import com.test.R;
import static android.content.ContentValues.TAG;
public class MaskedEditText extends AppCompatEditText implements TextWatcher {
public static final String SPACE = " ";
private String mask;
private char charRepresentation;
private boolean keepHint;
private int[] rawToMask;
private RawText rawText;
private boolean editingBefore;
private boolean editingOnChanged;
private boolean editingAfter;
private int[] maskToRaw;
private int selection;
private boolean initialized;
private boolean ignore;
protected int maxRawLength;
private int lastValidMaskPosition;
private boolean selectionChanged;
private OnFocusChangeListener focusChangeListener;
private String allowedChars;
private String deniedChars;
public MaskedEditText(Context context) {
super(context);
init();
}
public MaskedEditText(Context context, AttributeSet attrs) {
super(context, attrs);
init();
TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.MaskedEditText);
mask = attributes.getString(R.styleable.MaskedEditText_mask);
allowedChars = attributes.getString(R.styleable.MaskedEditText_allowed_chars);
deniedChars = attributes.getString(R.styleable.MaskedEditText_denied_chars);
String representation = attributes.getString(R.styleable.MaskedEditText_char_representation);
if (representation == null) {
charRepresentation = '#';
} else {
charRepresentation = representation.charAt(0);
}
keepHint = attributes.getBoolean(R.styleable.MaskedEditText_keep_hint, false);
cleanUp();
// Ignoring enter key presses
setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
switch (actionId) {
// case EditorInfo.IME_ACTION_NEXT:
// fixing actionNext
// return false;
default:
return true;
}
}
});
attributes.recycle();
}
#Override
public Parcelable onSaveInstanceState() {
final Parcelable superParcellable = super.onSaveInstanceState();
final Bundle state = new Bundle();
state.putParcelable("super", superParcellable);
state.putString("text", getRawText());
state.putBoolean("keepHint", isKeepHint());
return state;
}
#Override
public void onRestoreInstanceState(Parcelable state) {
Bundle bundle = (Bundle) state;
keepHint = bundle.getBoolean("keepHint", false);
super.onRestoreInstanceState(((Bundle) state).getParcelable("super"));
final String text = bundle.getString("text");
setText(text);
Log.d(TAG, "onRestoreInstanceState: " + text);
}
#Override
public void setText(CharSequence text, BufferType type) {
// if (text == null || text.equals("")) return;
super.setText(text, type);
}
/**
* #param listener - its onFocusChange() method will be called before performing MaskedEditText operations,
* related to this event.
*/
#Override
public void setOnFocusChangeListener(OnFocusChangeListener listener) {
focusChangeListener = listener;
}
private void cleanUp() {
initialized = false;
generatePositionArrays();
rawText = new RawText();
selection = rawToMask[0];
editingBefore = true;
editingOnChanged = true;
editingAfter = true;
if (hasHint() && rawText.length() == 0) {
this.setText(makeMaskedTextWithHint());
} else {
this.setText(makeMaskedText());
}
editingBefore = false;
editingOnChanged = false;
editingAfter = false;
maxRawLength = maskToRaw[previousValidPosition(mask.length() - 1)] + 1;
lastValidMaskPosition = findLastValidMaskPosition();
initialized = true;
super.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (focusChangeListener != null) {
focusChangeListener.onFocusChange(v, hasFocus);
}
if (hasFocus()) {
selectionChanged = false;
MaskedEditText.this.setSelection(lastValidPosition());
}
}
});
}
private int findLastValidMaskPosition() {
for (int i = maskToRaw.length - 1; i >= 0; i--) {
if (maskToRaw[i] != -1) return i;
}
throw new RuntimeException("Mask must contain at least one representation char");
}
private boolean hasHint() {
return getHint() != null;
}
public MaskedEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public void setMask(String mask) {
this.mask = mask;
cleanUp();
}
public String getMask() {
return this.mask;
}
public String getRawText() {
return this.rawText.getText();
}
public void setCharRepresentation(char charRepresentation) {
this.charRepresentation = charRepresentation;
cleanUp();
}
public char getCharRepresentation() {
return this.charRepresentation;
}
/**
* Generates positions for values characters. For instance:
* Input data: mask = "+7(###)###-##-##
* After method execution:
* rawToMask = [3, 4, 5, 6, 8, 9, 11, 12, 14, 15]
* maskToRaw = [-1, -1, -1, 0, 1, 2, -1, 3, 4, 5, -1, 6, 7, -1, 8, 9]
* charsInMask = "+7()- " (and space, yes)
*/
private void generatePositionArrays() {
int[] aux = new int[mask.length()];
maskToRaw = new int[mask.length()];
String charsInMaskAux = "";
int charIndex = 0;
for (int i = 0; i < mask.length(); i++) {
char currentChar = mask.charAt(i);
if (currentChar == charRepresentation) {
aux[charIndex] = i;
maskToRaw[i] = charIndex++;
} else {
String charAsString = Character.toString(currentChar);
if (!charsInMaskAux.contains(charAsString)) {
charsInMaskAux = charsInMaskAux.concat(charAsString);
}
maskToRaw[i] = -1;
}
}
if (charsInMaskAux.indexOf(' ') < 0) {
charsInMaskAux = charsInMaskAux + SPACE;
}
char[] charsInMask = charsInMaskAux.toCharArray();
rawToMask = new int[charIndex];
for (int i = 0; i < charIndex; i++) {
rawToMask[i] = aux[i];
}
}
private void init() {
addTextChangedListener(this);
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
if (!editingBefore) {
editingBefore = true;
if (start > lastValidMaskPosition) {
ignore = true;
}
int rangeStart = start;
if (after == 0) {
rangeStart = erasingStart(start);
}
Range range = calculateRange(rangeStart, start + count);
if (range.getStart() != -1) {
rawText.subtractFromString(range);
}
if (count > 0) {
selection = previousValidPosition(start);
}
}
}
private int erasingStart(int start) {
while (start > 0 && maskToRaw[start] == -1) {
start--;
}
return start;
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (!editingOnChanged && editingBefore) {
editingOnChanged = true;
if (ignore) {
return;
}
if (count > 0) {
int startingPosition = maskToRaw[nextValidPosition(start)];
String addedString = s.subSequence(start, start + count).toString();
count = rawText.addToString(clear(addedString), startingPosition, maxRawLength);
if (initialized) {
int currentPosition;
if (startingPosition + count < rawToMask.length)
currentPosition = rawToMask[startingPosition + count];
else
currentPosition = lastValidMaskPosition + 1;
selection = nextValidPosition(currentPosition);
}
}
}
}
#Override
public void afterTextChanged(Editable s) {
if (!editingAfter && editingBefore && editingOnChanged) {
editingAfter = true;
if (hasHint() && (keepHint || rawText.length() == 0)) {
setText(makeMaskedTextWithHint());
} else {
setText(makeMaskedText());
}
selectionChanged = false;
setSelection(selection);
editingBefore = false;
editingOnChanged = false;
editingAfter = false;
ignore = false;
}
}
public boolean isKeepHint() {
return keepHint;
}
public void setKeepHint(boolean keepHint) {
this.keepHint = keepHint;
setText(getRawText());
}
#Override
protected void onSelectionChanged(int selStart, int selEnd) {
// On Android 4+ this method is being called more than 1 time if there is a hint in the EditText, what moves the cursor to left
// Using the boolean var selectionChanged to limit to one execution
if (initialized) {
if (!selectionChanged) {
selStart = fixSelection(selStart);
selEnd = fixSelection(selEnd);
// exactly in this order. If getText.length() == 0 then selStart will be -1
if (selStart > getText().length()) selStart = getText().length();
if (selStart < 0) selStart = 0;
// exactly in this order. If getText.length() == 0 then selEnd will be -1
if (selEnd > getText().length()) selEnd = getText().length();
if (selEnd < 0) selEnd = 0;
setSelection(selStart, selEnd);
selectionChanged = true;
} else {
//check to see if the current selection is outside the already entered text
if (selStart > rawText.length() - 1) {
final int start = fixSelection(selStart);
final int end = fixSelection(selEnd);
if (start >= 0 && end < getText().length()) {
setSelection(start, end);
}
}
}
}
super.onSelectionChanged(selStart, selEnd);
}
private int fixSelection(int selection) {
if (selection > lastValidPosition()) {
return lastValidPosition();
} else {
return nextValidPosition(selection);
}
}
private int nextValidPosition(int currentPosition) {
while (currentPosition < lastValidMaskPosition && maskToRaw[currentPosition] == -1) {
currentPosition++;
}
if (currentPosition > lastValidMaskPosition) return lastValidMaskPosition + 1;
return currentPosition;
}
private int previousValidPosition(int currentPosition) {
while (currentPosition >= 0 && maskToRaw[currentPosition] == -1) {
currentPosition--;
if (currentPosition < 0) {
return nextValidPosition(0);
}
}
return currentPosition;
}
private int lastValidPosition() {
if (rawText.length() == maxRawLength) {
return rawToMask[rawText.length() - 1] + 1;
}
return nextValidPosition(rawToMask[rawText.length()]);
}
private String makeMaskedText() {
int maskedTextLength;
if (rawText.length() < rawToMask.length) {
maskedTextLength = rawToMask[rawText.length()];
} else {
maskedTextLength = mask.length();
}
char[] maskedText = new char[maskedTextLength]; //mask.replace(charRepresentation, ' ').toCharArray();
for (int i = 0; i < maskedText.length; i++) {
int rawIndex = maskToRaw[i];
if (rawIndex == -1) {
maskedText[i] = mask.charAt(i);
} else {
maskedText[i] = rawText.charAt(rawIndex);
}
}
return new String(maskedText);
}
private CharSequence makeMaskedTextWithHint() {
SpannableStringBuilder ssb = new SpannableStringBuilder();
int mtrv;
int maskFirstChunkEnd = rawToMask[0];
for (int i = 0; i < mask.length(); i++) {
mtrv = maskToRaw[i];
if (mtrv != -1) {
if (mtrv < rawText.length()) {
ssb.append(rawText.charAt(mtrv));
} else {
ssb.append(getHint().charAt(maskToRaw[i]));
}
} else {
ssb.append(mask.charAt(i));
}
if ((keepHint && rawText.length() < rawToMask.length && i >= rawToMask[rawText.length()])
|| (!keepHint && i >= maskFirstChunkEnd)) {
ssb.setSpan(new ForegroundColorSpan(getCurrentHintTextColor()), i, i + 1, 0);
}
}
return ssb;
}
private Range calculateRange(int start, int end) {
Range range = new Range();
for (int i = start; i <= end && i < mask.length(); i++) {
if (maskToRaw[i] != -1) {
if (range.getStart() == -1) {
range.setStart(maskToRaw[i]);
}
range.setEnd(maskToRaw[i]);
}
}
if (end == mask.length()) {
range.setEnd(rawText.length());
}
if (range.getStart() == range.getEnd() && start < end) {
int newStart = previousValidPosition(range.getStart() - 1);
if (newStart < range.getStart()) {
range.setStart(newStart);
}
}
return range;
}
private String clear(String string) {
if (deniedChars != null) {
for (char c : deniedChars.toCharArray()) {
string = string.replace(Character.toString(c), "");
}
}
if (allowedChars != null) {
StringBuilder builder = new StringBuilder(string.length());
for (char c : string.toCharArray()) {
if (allowedChars.contains(String.valueOf(c))) {
builder.append(c);
}
}
string = builder.toString();
}
return string;
}
}
In activity_main.xml
<com.test.PhoneNumberFormatter.MaskedEditText
android:id="#+id/phone_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"
android:hint="#string/phone_number"
android:imeOptions="actionNext"
android:inputType="textPhonetic"
android:paddingBottom="#dimen/_3sdp"
android:paddingTop="#dimen/_8sdp"
android:textColorHint="#color/grey_color"
android:textSize="#dimen/_12sdp"
mask:allowed_chars="1234567890ext."
mask:keep_hint="false"
mask:mask="(###)###-#### ext.######" />
Thanks.
For format Edit-text, below things can be helpful to you.
**Step 1** : Add following line in your build.gradle file
implementation 'com.github.pinball83:masked-edittext:1.0.4'
**Step 2 :** by xml :
<com.github.pinball83.maskededittext.MaskedEditText
android:id="#+id/masked_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
app:mask="8 (***) *** **-**"
app:notMaskedSymbol="*"
app:maskIcon="#drawable/abc_ic_clear_mtrl_alpha"
app:maskIconColor="#color/colorPrimary"
/>
or by java file :
MaskedEditText maskedEditText = new MaskedEditText.Builder(context)
.mask("8 (***) *** **-**")
.notMaskedSymbol("*")
.icon(R.drawable.ic_account_circle)
.iconCallback(unmaskedText -> { //Icon click callback handler })
.build();
MaskedEditText editText = new MaskedEditText.Builder(context)
.mask("8 (***) *** **-**")
.notMaskedSymbol("*")
.build();; //set mask to "8 (***) *** **-**" and not masked symbol to "*"
Text setup and formatting
MaskedEditText editText = new MaskedEditText..Builder(context)
.mask("8 (***) *** **-**")
.notMaskedSymbol("*")
.format("[1][2][3] [4][5][6]-[7][8]-[10][9]")//set format of returned data input into MaskedEditText
.build();
editText.setMaskedText("5551235567");
for more details use following url :
https://github.com/pinball83/Masked-Edittext
Enjoy :)
Step 1 : Create editText
<EditText
android:id="#+id/masked_edit_text"
android:layout_width="yourSize"
android:layout_height="yourSize"
android:inputType="textPassword"/>
Step2:
public class CustomTransformation extends PasswordTransformationMethod {
#Override
public CharSequence getTransformation(CharSequence source, View view) {
return new TransformedSequence(source);
}
private class TransformedSequence implements CharSequence {
private CharSequence sequence;
public TransformedSequence(CharSequence source) {
sequence = source; // Store char sequence
}
public char charAt(int index) {
return 'X'; // Replace with what you want.
}
public int length() {
return sequence.length(); // return the length
}
public CharSequence subSequence(int start, int end) {
return sequence.subSequence(start, end); //return sequence
}
}
Step 3: apply the transformation
EditText edittext = findViewById(R.id.masked_edit_text);
edittext.setTransformationMethod(new CustomTransformation());
https://github.com/mukeshsolanki/country-picker-android
try this library .
this will automatically mask your edittext with selected country number .

Android Custom Keyboard stuck When Swapping to/from Another Keyboard

I'm developing a custom keyboard for Android that will store login credentials in a local database (plan is to encrypt the DB after the thing works flawlessly).
The keyboard has a basic layout with a KeyboardView at the bottom and a 'Switch Keyboard' button at the top-right corner.
Everything works fine except that when i click the switch button, things start to fail.
Scenario:
1) My keyboard is active and everything is fine. Keyboard visibility is managed by the system.
2) I click the switch button, my keyboard is closed and previously enabled keyboard is displayed.
3) Now i open the Keyboard Chooser through Notification Tray and re-enable my custom keyboard.
My keyboard is set as default, but there's no keyboard on the screen. when i touch the bottom half of screen area where keyboard appears, the characters are being typed (yes, my keyboard is there but is invisible!).
I press the Back key on my phone and the system doesn't close the keyboard and it's stuck there.
I press the Home key and the keyboard becomes visible for a few milliseconds, is closed by the system and i'm sent to the Home Screen.
I've tried waiting for the keyboard to appear, etc. and also tried the app on 3 other phones from different make. Also, i'm developing the app for Lollipop (API 21 and higher).
Here's the code:
1) InputMethodService:
public class HomlesInputService extends InputMethodService implements KeyboardView.OnKeyboardActionListener {
CustomKeyboardView kv;
Keyboard qwertyKeyboard, symbolKeyboard;
Boolean caps;
private String myPwd, myUid;
SharedPreferences mPrefs;
SharedPreferences.Editor mEdit;
Boolean isPassword, isUid, uidFilled, pwdFilled;
Vibrator vibrator;
View keyboard;
EditorInfo sEditorInfo;
SQLiteDatabase db;
InputMethodManager imm;
IBinder token;
String defImeId;
public static final int SYM_KEYBOARD = -10;
public static final int GO_BUTTON = -4;
public static final double GO_BUTTON_ASPECT_RATIO = 1.88;
public static final double NEXT_BUTTON_ASPECT_RATIO = 1;
public HomlesInputService() {
}
#Override
public void onCreate() {
super.onCreate();
mPrefs = getSharedPreferences(Constants.APP_PREFS, MODE_PRIVATE);
mEdit = mPrefs.edit();
//storing ime id in prefs
String myId = Settings.Secure.getString(getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
mEdit.putString(Constants.MY_IME_ID, myId);
mEdit.commit();
imm = (InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE);
defImeId = mPrefs.getString(Constants.DEFAULT_KEYBOARD, null); //the id of previous IME stored in preferences (found correct in debugging)
qwertyKeyboard = new Keyboard(this, R.xml.qwerty_keyboard_layout);
symbolKeyboard = new Keyboard(this, R.xml.symbol_keyboard_layout);
db = openOrCreateDatabase(DbConstants.DATABASE_NAME, MODE_PRIVATE, null);
db.execSQL("CREATE TABLE IF NOT EXISTS " + DbConstants.TABLE_NAME + "("
+ DbConstants.APP_ID + "," + DbConstants.UID_VALUE + "," + DbConstants.PWD_VALUE + ")");
vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
}
#Override
public View onCreateInputView() {
keyboard = getLayoutInflater().inflate(R.layout.my_custom_keyboard, null);
ImageView ivRevertKeyboard = (ImageView) keyboard.findViewById(R.id.ivRevertKeyboard); //this button is used to switch to previous IME
token = this.getWindow().getWindow().getAttributes().token;
if (defImeId != null) {
ivRevertKeyboard.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
vibrator.vibrate(Constants.VIBRATE_TIME_MEDIUM);
try {
imm.hideSoftInputFromInputMethod(token, 0);
imm.setInputMethod(token, defImeId);
} catch (Throwable t) { // java.lang.NoSuchMethodError if API_level<11
t.printStackTrace();
}
}
});
} else {
ivRevertKeyboard.setVisibility(View.GONE);
}
kv = (CustomKeyboardView) keyboard.findViewById(R.id.keyboard);
kv.setKeyboard(qwertyKeyboard);
kv.setOnKeyboardActionListener(this);
caps = false;
myPwd = "";
myUid = "";
isPassword = false;
return keyboard;
}
#Override
public void onStartInputView(EditorInfo info, boolean restarting) {
sEditorInfo = info;
uidFilled = false;
pwdFilled = false;
if (info.inputType == 129) {
isPassword = true;
} else {
isPassword = false;
}
CharSequence CHARbeforeCursor = getCurrentInputConnection().getTextBeforeCursor(999, 0);
CharSequence CHARafterCursor = getCurrentInputConnection().getTextAfterCursor(999, 0);
if (CHARbeforeCursor != null && CHARafterCursor != null) {
String beforeCursor = CHARbeforeCursor.toString();
String afterCursor = CHARafterCursor.toString();
if (isPassword) {
myPwd = beforeCursor + afterCursor;
} else {
myUid = beforeCursor + afterCursor;
}
}
setGoButton();
}
private void setGoButton() {
List<Keyboard.Key> keys = kv.getKeyboard().getKeys();
Drawable dr;
int rowHeight, goBtWidth = 0, nextBtWidth = 0;
rowHeight = Utils.dpToPx(40, getApplicationContext());
goBtWidth = Integer.parseInt("" + Math.round(rowHeight * GO_BUTTON_ASPECT_RATIO));
nextBtWidth = Integer.parseInt("" + Math.round(rowHeight * NEXT_BUTTON_ASPECT_RATIO));
for (int i = 0; i < keys.size(); i++) {
Keyboard.Key key = keys.get(i);
int code = key.codes[0];
if (code == GO_BUTTON) {
if (isPassword) {
key.width = goBtWidth;
dr = getResources().getDrawable(R.drawable.keyboard_save_and_go, getApplicationContext().getTheme());
} else {
key.width = nextBtWidth;
dr = getResources().getDrawable(R.drawable.keyboard_next, getApplicationContext().getTheme());
}
key.icon = dr;
}
}
}
#Override
public void onPress(int primaryCode) {
vibrator.vibrate(Constants.VIBRATE_TIME_SHORT);
switch (primaryCode) {
case Keyboard.KEYCODE_DELETE:
kv.setPreviewEnabled(false);
break;
case Keyboard.KEYCODE_SHIFT:
kv.setPreviewEnabled(false);
break;
case Keyboard.KEYCODE_DONE:
kv.setPreviewEnabled(false);
break;
case SYM_KEYBOARD:
kv.setPreviewEnabled(false);
break;
case 32:
kv.setPreviewEnabled(false);
break;
default:
kv.setPreviewEnabled(true);
}
}
#Override
public void onRelease(int i) {
}
#Override
public void onKey(int primaryCode, int[] ints) {
InputConnection conn = getCurrentInputConnection();
uidFilled = mPrefs.getBoolean(Constants.UID_FILLED, false);
pwdFilled = mPrefs.getBoolean(Constants.PWD_FILLED, false);
switch (primaryCode) {
case Keyboard.KEYCODE_DELETE:
conn.deleteSurroundingText(1, 0);
if (isPassword) {
if (myPwd.length() > 0) {
String beforeCursor = conn.getTextBeforeCursor(myPwd.length(), 0).toString();
beforeCursor = beforeCursor.substring(0, beforeCursor.length());
String afterCursor = conn.getTextAfterCursor(myPwd.length(), 0).toString();
myPwd = beforeCursor + afterCursor;
if (uidFilled && pwdFilled) {
mEdit.putString(Constants.EDIT_NEW_PWD, myPwd);
} else {
mEdit.putString(Constants.NEW_PWD, myPwd);
}
mEdit.commit();
Log.d("##Pwd saved", "" + mPrefs.getString(Constants.NEW_PWD, ""));
}
} else {
if (myUid.length() > 0) {
String beforeCursor = conn.getTextBeforeCursor(myUid.length(), 0).toString();
beforeCursor = beforeCursor.substring(0, beforeCursor.length());
String afterCursor = conn.getTextAfterCursor(myUid.length(), 0).toString();
myUid = beforeCursor + afterCursor;
if (uidFilled && pwdFilled) {
mEdit.putString(Constants.EDIT_NEW_UID, myUid);
} else {
mEdit.putString(Constants.NEW_UID, myUid);
}
mEdit.commit();
Log.d("##Uid saved", "" + mPrefs.getString(Constants.NEW_UID, ""));
}
}
break;
case Keyboard.KEYCODE_SHIFT:
caps = !caps;
kv.setShifted(caps);
kv.invalidateAllKeys();
break;
case Keyboard.KEYCODE_DONE:
switch (sEditorInfo.imeOptions & (EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION)) {
case EditorInfo.IME_ACTION_GO:
conn.performEditorAction(EditorInfo.IME_ACTION_GO);
break;
case EditorInfo.IME_ACTION_NEXT:
conn.performEditorAction(EditorInfo.IME_ACTION_NEXT);
break;
case EditorInfo.IME_ACTION_SEARCH:
conn.performEditorAction(EditorInfo.IME_ACTION_SEARCH);
break;
case EditorInfo.IME_ACTION_SEND:
conn.performEditorAction(EditorInfo.IME_ACTION_SEND);
break;
case EditorInfo.IME_ACTION_DONE:
saveCredentialsToDb();
conn.performEditorAction(EditorInfo.IME_ACTION_DONE);
//triggers login
break;
default:
conn.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
break;
}
break;
case SYM_KEYBOARD:
Keyboard currentKeyb = kv.getKeyboard();
if (currentKeyb == symbolKeyboard) {
kv.setKeyboard(qwertyKeyboard);
} else {
kv.setKeyboard(symbolKeyboard);
}
setGoButton();
break;
default:
char code = (char) primaryCode;
if (Character.isLetter(code) && caps) {
code = Character.toUpperCase(code);
}
if (isPassword) {
myPwd = myPwd + code;
if (uidFilled && pwdFilled) {
mEdit.putString(Constants.EDIT_NEW_PWD, myPwd);
} else {
mEdit.putString(Constants.NEW_PWD, myPwd);
}
mEdit.commit();
Log.d("##Pwd saved", "" + mPrefs.getString(Constants.NEW_PWD, ""));
} else {
myUid = myUid + code;
if (uidFilled && pwdFilled) {
mEdit.putString(Constants.EDIT_NEW_UID, myUid);
} else {
mEdit.putString(Constants.NEW_UID, myUid);
}
mEdit.commit();
Log.d("##Uid saved", "" + mPrefs.getString(Constants.NEW_UID, ""));
}
conn.commitText(String.valueOf(code), 1);
}
}
private void saveCredentialsToDb() {
db = openOrCreateDatabase(DbConstants.DATABASE_NAME, MODE_PRIVATE, null);
String activityDbId = getCurrentInputEditorInfo().packageName;
if (myUid == null || myUid.length() <= 0) {
Toast.makeText(getApplicationContext(), "Enter the Username", Toast.LENGTH_SHORT).show();
return;
} else if (myPwd == null || myPwd.length() <= 0) {
Toast.makeText(getApplicationContext(), "Enter the Password", Toast.LENGTH_SHORT).show();
return;
} else if (activityDbId == null && activityDbId.length() <= 0) {
Toast.makeText(getApplicationContext(), "Failed to get app ID", Toast.LENGTH_SHORT).show();
return;
}
Log.d("##Activity pkg name", "" + activityDbId);
ContentValues cv = new ContentValues();
cv.put(DbConstants.APP_ID, activityDbId);
cv.put(DbConstants.UID_VALUE, myUid);
cv.put(DbConstants.PWD_VALUE, myPwd);
if (uidFilled && pwdFilled) {
String oldUid = mPrefs.getString(Constants.EDIT_OLD_UID, null);
String oldPwd = mPrefs.getString(Constants.EDIT_OLD_PWD, null);
if (oldUid != null && oldPwd != null) {
if (oldUid.contentEquals(myUid) && oldPwd.contentEquals(myPwd)) {
Toast.makeText(getApplicationContext(), "Unchanged values.", Toast.LENGTH_SHORT).show();
return;
}
db.update(DbConstants.TABLE_NAME, cv, DbConstants.APP_ID + "=?" + " AND " + DbConstants.UID_VALUE + "=?", new String[]{activityDbId, oldUid});
mEdit.remove(Constants.EDIT_OLD_UID);
mEdit.remove(Constants.EDIT_NEW_UID);
mEdit.remove(Constants.EDIT_NEW_PWD);
mEdit.putBoolean(Constants.UID_FILLED, false);
mEdit.putBoolean(Constants.PWD_FILLED, false);
mEdit.commit();
uidFilled = false;
pwdFilled = false;
Toast.makeText(getApplicationContext(), "Credentials edited!", Toast.LENGTH_SHORT).show();
}
} else {
Cursor cr2 = db.query(DbConstants.TABLE_NAME, null, DbConstants.APP_ID + "=?" + " AND " + DbConstants.UID_VALUE + "=?", new String[]{activityDbId, myUid}, null, null, null);
if (cr2.moveToNext()) {
db.update(DbConstants.TABLE_NAME, cv, DbConstants.APP_ID + "=?" + " AND " + DbConstants.UID_VALUE + "=?", new String[]{activityDbId, myUid});
Toast.makeText(getApplicationContext(), "Credentials edited!", Toast.LENGTH_SHORT).show();
} else {
db.insert(DbConstants.TABLE_NAME, null, cv);
Log.d("Stored:" + activityDbId, myUid + "->" + myPwd);
mEdit.remove(Constants.NEW_UID);
mEdit.remove(Constants.NEW_PWD);
mEdit.commit();
Toast.makeText(getApplicationContext(), "Credentials stored!", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onFinishInput() {
super.onFinishInput();
Log.d("onFinishInput", "invoked");
}
#Override
public void onText(CharSequence charSequence) {
}
#Override
public void swipeLeft() {
}
#Override
public void swipeRight() {
}
#Override
public void swipeDown() {
}
#Override
public void swipeUp() {
}
}
2) CustomKeyboardView:
public class CustomKeyboardView extends KeyboardView {
Context mContext;
Boolean caps;
public CustomKeyboardView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
caps = false;
}
#Override
public boolean setShifted(boolean shifted) {
super.setShifted(shifted);
caps = shifted;
invalidateAllKeys();
return shifted;
}
#Override
public void onDraw(Canvas canvas) {
List<Keyboard.Key> keys = getKeyboard().getKeys();
for (Keyboard.Key key : keys) {
Drawable dr = null;
if (key.codes[0] == Keyboard.KEYCODE_DELETE) {
dr = getResources().getDrawable(R.drawable.keyboard_backspace, mContext.getTheme());
dr.setBounds(key.x, key.y, key.x + key.width, key.y + key.height);
dr.draw(canvas);
} else if (key.codes[0] == Keyboard.KEYCODE_SHIFT) {
dr = getResources().getDrawable(R.drawable.keyboard_shift, mContext.getTheme());
dr.setBounds(key.x, key.y, key.x + key.width, key.y + key.height);
dr.draw(canvas);
} else if (key.codes[0] == 32) { //space bar
int tenDp = Utils.dpToPx(10, mContext);
int twoDp = Utils.dpToPx(2, mContext);
dr = new ColorDrawable(Color.LTGRAY);
dr.setBounds(key.x + twoDp, key.y + (tenDp), key.x + key.width - twoDp, key.y + key.height - (tenDp));
dr.draw(canvas);
}
Paint mPaint = new Paint();
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setTextSize(Utils.dpToPx(18, mContext));
mPaint.setColor(Color.BLACK);
if (key.label != null) {
String keyLabel = key.label.toString();
if (caps) {
keyLabel = keyLabel.toUpperCase();
}
canvas.drawText(keyLabel, key.x + (key.width / 2),
key.y + (key.height / 2) + Utils.dpToPx(5, mContext), mPaint);
} else if (key.icon != null) {
key.icon.setBounds(key.x, key.y, key.x + key.width, key.y + key.height);
key.icon.draw(canvas);
}
}
}
}
3) R.layout.my_custom_keyboard:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"
android:orientation="vertical"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/blue">
<ImageView
android:id="#+id/ivRevertKeyboard"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentRight="true"
android:padding="10dp"
android:scaleType="fitEnd"
android:src="#drawable/keyboard_icon" />
</RelativeLayout>
<com.prasad.CustomKeyboardView
android:id="#+id/keyboard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="2dp"
android:layout_marginRight="2dp"
android:layout_marginTop="5dp"
android:keyPreviewHeight="50dp"
android:background="#color/white"
android:keyPreviewLayout="#xml/keyboard_preview"
android:shadowColor="#color/transparent" />
</LinearLayout>
Expected behaviour: The keyboard should be displayed and hidden properly by the system after swapping multiple times with another keyboard.
Please let me know if you need additional details. Any clues will be appreciated.
Regards,
Prasad
how is this?
#Override
public void onClick(View view) {
vibrator.vibrate(Constants.VIBRATE_TIME_MEDIUM);
try {
// imm.hideSoftInputFromInputMethod(token, 0);
// imm.setInputMethod(token, defImeId);
this.switchInputMethod(defImeId);
} catch (Throwable t) { // java.lang.NoSuchMethodError if API_level<11
t.printStackTrace();
}
}

Reciprocal in Android code for calculator

This is the code for a calculator app for Android I'm making:
package com.example.calculator;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Iterator;
import java.util.Stack;
import android.app.Activity;
import android.os.Bundle;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
import android.view.View;
import android.view.View.OnClickListener;
public class main extends Activity {
GridView mKeypadGrid;
TextView userInputText;
TextView memoryStatText;
Stack<String> mInputStack;
Stack<String> mOperationStack;
KeypadAdapter mKeypadAdapter;
TextView mStackText;
boolean resetInput = false;
boolean hasFinalResult = false;
String mDecimalSeperator;
double memoryValue = Double.NaN;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DecimalFormat currencyFormatter = (DecimalFormat) NumberFormat
.getInstance();
char decimalSeperator = currencyFormatter.getDecimalFormatSymbols()
.getDecimalSeparator();
mDecimalSeperator = Character.toString(decimalSeperator);
setContentView(R.layout.main);
// Create the stack
mInputStack = new Stack<String>();
mOperationStack = new Stack<String>();
// Get reference to the keypad button GridView
mKeypadGrid = (GridView) findViewById(R.id.grdButtons);
// Get reference to the user input TextView
userInputText = (TextView) findViewById(R.id.txtInput);
userInputText.setText("0");
memoryStatText = (TextView) findViewById(R.id.txtMemory);
memoryStatText.setText("");
mStackText = (TextView) findViewById(R.id.txtStack);
// Create Keypad Adapter
mKeypadAdapter = new KeypadAdapter(this);
// Set adapter of the keypad grid
mKeypadGrid.setAdapter(mKeypadAdapter);
// Set button click listener of the keypad adapter
mKeypadAdapter.setOnButtonClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Button btn = (Button) v;
// Get the KeypadButton value which is used to identify the
// keypad button from the Button's tag
KeypadButton keypadButton = (KeypadButton) btn.getTag();
// Process keypad button
ProcessKeypadInput(keypadButton);
}
});
mKeypadGrid.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
}
});
}
private void ProcessKeypadInput(KeypadButton keypadButton) {
//Toast.makeText(this, keypadButton.getText(), Toast.LENGTH_SHORT).show();
String text = keypadButton.getText().toString();
String currentInput = userInputText.getText().toString();
int currentInputLen = currentInput.length();
String evalResult = null;
double userInputValue = Double.NaN;
switch (keypadButton) {
case BACKSPACE: // Handle backspace
// If has operand skip backspace
if (resetInput)
return;
int endIndex = currentInputLen - 1;
// There is one character at input so reset input to 0
if (endIndex < 1) {
userInputText.setText("0");
}
// Trim last character of the input text
else {
userInputText.setText(currentInput.subSequence(0, endIndex));
}
break;
case SIGN: // Handle -/+ sign
// input has text and is different than initial value 0
if (currentInputLen > 0 && currentInput != "0") {
// Already has (-) sign. Remove that sign
if (currentInput.charAt(0) == '-') {
userInputText.setText(currentInput.subSequence(1,
currentInputLen));
}
// Prepend (-) sign
else {
userInputText.setText("-" + currentInput.toString());
}
}
break;
case CE: // Handle clear input
userInputText.setText("0");
break;
case INVERT:
if (currentInput != "0") {
userInputText.setText("1/" + currentInput);
}
break;
case C: // Handle clear input and stack
userInputText.setText("0");
clearStacks();
break;
case DECIMAL_SEP: // Handle decimal separator
if (hasFinalResult || resetInput) {
userInputText.setText("0" + mDecimalSeperator);
hasFinalResult = false;
resetInput = false;
} else if (currentInput.contains("."))
return;
else
userInputText.append(mDecimalSeperator);
break;
case DIV:
case PLUS:
case MINUS:
case MULTIPLY:
if (resetInput) {
mInputStack.pop();
mOperationStack.pop();
} else {
if (currentInput.charAt(0) == '-') {
mInputStack.add("(" + currentInput + ")");
} else {
mInputStack.add(currentInput);
}
mOperationStack.add(currentInput);
}
mInputStack.add(text);
mOperationStack.add(text);
dumpInputStack();
evalResult = evaluateResult(false);
if (evalResult != null)
userInputText.setText(evalResult);
resetInput = true;
break;
case CALCULATE:
if (mOperationStack.size() == 0)
break;
mOperationStack.add(currentInput);
evalResult = evaluateResult(true);
if (evalResult != null) {
clearStacks();
userInputText.setText(evalResult);
resetInput = false;
hasFinalResult = true;
}
break;
case M_ADD: // Add user input value to memory buffer
userInputValue = tryParseUserInput();
if (Double.isNaN(userInputValue))
return;
if (Double.isNaN(memoryValue))
memoryValue = 0;
memoryValue += userInputValue;
displayMemoryStat();
hasFinalResult = true;
break;
case M_REMOVE: // Subtract user input value to memory buffer
userInputValue = tryParseUserInput();
if (Double.isNaN(userInputValue))
return;
if (Double.isNaN(memoryValue))
memoryValue = 0;
memoryValue -= userInputValue;
displayMemoryStat();
hasFinalResult = true;
break;
case MC: // Reset memory buffer to 0
memoryValue = Double.NaN;
displayMemoryStat();
break;
case MR: // Read memoryBuffer value
if (Double.isNaN(memoryValue))
return;
userInputText.setText(doubleToString(memoryValue));
displayMemoryStat();
break;
case MS: // Set memoryBuffer value to user input
userInputValue = tryParseUserInput();
if (Double.isNaN(userInputValue))
return;
memoryValue = userInputValue;
displayMemoryStat();
hasFinalResult = true;
break;
default:
if (Character.isDigit(text.charAt(0))) {
if (currentInput.equals("0") || resetInput || hasFinalResult) {
userInputText.setText(text);
resetInput = false;
hasFinalResult = false;
} else {
userInputText.append(text);
resetInput = false;
}
}
break;
}
}
private void clearStacks() {
mInputStack.clear();
mOperationStack.clear();
mStackText.setText("");
}
private void dumpInputStack() {
Iterator<String> it = mInputStack.iterator();
StringBuilder sb = new StringBuilder();
while (it.hasNext()) {
CharSequence iValue = it.next();
sb.append(iValue);
}
mStackText.setText(sb.toString());
}
private String evaluateResult(boolean requestedByUser) {
if ((!requestedByUser && mOperationStack.size() != 4)
|| (requestedByUser && mOperationStack.size() != 3))
return null;
String left = mOperationStack.get(0);
String operator = mOperationStack.get(1);
String right = mOperationStack.get(2);
String tmp = null;
if (!requestedByUser)
tmp = mOperationStack.get(3);
double leftVal = Double.parseDouble(left.toString());
double rightVal = Double.parseDouble(right.toString());
double result = Double.NaN;
if (operator.equals(KeypadButton.DIV.getText())) {
result = leftVal / rightVal;
} else if (operator.equals(KeypadButton.MULTIPLY.getText())) {
result = leftVal * rightVal;
} else if (operator.equals(KeypadButton.PLUS.getText())) {
result = leftVal + rightVal;
} else if (operator.equals(KeypadButton.MINUS.getText())) {
result = leftVal - rightVal;
}
String resultStr = doubleToString(result);
if (resultStr == null)
return null;
mOperationStack.clear();
if (!requestedByUser) {
mOperationStack.add(resultStr);
mOperationStack.add(tmp);
}
return resultStr;
}
private String doubleToString(double value) {
if (Double.isNaN(value))
return null;
long longVal = (long) value;
if (longVal == value)
return Long.toString(longVal);
else
return Double.toString(value);
}
private double tryParseUserInput() {
String inputStr = userInputText.getText().toString();
double result = Double.NaN;
try {
result = Double.parseDouble(inputStr);
} catch (NumberFormatException nfe) {
}
return result;
}
private void displayMemoryStat() {
if (Double.isNaN(memoryValue)) {
memoryStatText.setText("");
} else {
memoryStatText.setText("M = " + doubleToString(memoryValue));
}
}
}
To find the reciprocal of an inputted number, I use the following code:
case INVERT:
if (currentInput != "0") {
userInputText.setText("1/" + currentInput);
}
break;
But instead of displaying the output of the reciprocal, like I wanted, it simply displays "1/inputted number". Why is this, and can someone help me fix it? Thanks in advance.
You are returning it as text and so that is how it is displayed. You need to do the math then convert it to a string:
float input = Float.valueOf(currentInput);
if( input == 0) // Check if 0 to avoid divide by 0 error
userInputText.setText("NaN");
else
userInputText.setText(Float.toString(1/input));
double inputVal = Double.valueOf(currentInput);
userInputText.setText(inputVal != 0 ? String.valueOf(1/inputVal) : "NaN");

Connect to a Public wifi Network from Android Code?

I am developing an Android App that requires me to scan all available public wifi networks and connect to the one with highest signal strength. Can this be achieved is so HOW?
Right now my app just turns on wifi and connects to a saved network.
First have a look at the official help:
http://developer.android.com/reference/android/net/wifi/WifiManager.html
then look around and found something like that:
How can I get Android Wifi Scan Results into a list?
ScanResult gives the rssi (level)that can be used to select the appropriate network:
http://developer.android.com/reference/android/net/wifi/ScanResult.html
Here's a simple code to scan:
WifiManager wifi= (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifi.startScan();
// get list of the results in object format ( like an array )
List<ScanResult> results = wifi.getScanResults();`
// loop that goes through list
for (ScanResult result : results) {
Toast.makeText(this, result.SSID + " " + result.level,
Toast.LENGTH_SHORT).show();
}
Remember you need permsissions in your manifest.xml:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
UPDATE:
To create a network by SSID I use the following:
private boolean addNetworkAndActivate(ScanResult scanResult) {
WifiConfiguration wc = null;
List<WifiConfiguration> configs = wifiManager.getConfiguredNetworks();
for (WifiConfiguration wifiConfiguration : configs) {
try {
if (wifiConfiguration.SSID.equals("\"" + scanResult.SSID + "\"")) {
wc = wifiConfiguration;
break;
}
} catch (Exception e) {
}
}
// not configured, create new
if (wc == null) {
wc = new WifiConfiguration();
ConfigurationSecuritiesV8 conf = new ConfigurationSecuritiesV8();
conf.setupSecurity(wc, conf.getScanResultSecurity(scanResult), "7ej8e4jka9");
wc.SSID = "\"" + scanResult.SSID + "\"";
int res = wifiManager.addNetwork(wc);
if (res == -1)
return false;
if (!wifiManager.saveConfiguration())
return false;
}
boolean active = wifiManager.enableNetwork(wc.networkId, true);
return active;
}
Classes:
public class ConfigurationSecuritiesV8 extends ConfigurationSecurities {
static final int SECURITY_NONE = 0;
static final int SECURITY_WEP = 1;
static final int SECURITY_PSK = 2;
static final int SECURITY_EAP = 3;
enum PskType {
UNKNOWN, WPA, WPA2, WPA_WPA2
}
private static final String TAG = "ConfigurationSecuritiesV14";
private static int getSecurity(WifiConfiguration config) {
if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
return SECURITY_PSK;
}
if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP) || config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
return SECURITY_EAP;
}
return (config.wepKeys[0] != null) ? SECURITY_WEP : SECURITY_NONE;
}
private static int getSecurity(ScanResult result) {
if (result.capabilities.contains("WEP")) {
return SECURITY_WEP;
} else if (result.capabilities.contains("PSK")) {
return SECURITY_PSK;
} else if (result.capabilities.contains("EAP")) {
return SECURITY_EAP;
}
return SECURITY_NONE;
}
#Override
public String getWifiConfigurationSecurity(WifiConfiguration wifiConfig) {
return String.valueOf(getSecurity(wifiConfig));
}
#Override
public String getScanResultSecurity(ScanResult scanResult) {
return String.valueOf(getSecurity(scanResult));
}
#Override
public void setupSecurity(WifiConfiguration config, String security, String password) {
config.allowedAuthAlgorithms.clear();
config.allowedGroupCiphers.clear();
config.allowedKeyManagement.clear();
config.allowedPairwiseCiphers.clear();
config.allowedProtocols.clear();
final int sec = security == null ? SECURITY_NONE : Integer.valueOf(security);
final int passwordLen = password == null ? 0 : password.length();
switch (sec) {
case SECURITY_NONE:
config.allowedKeyManagement.set(KeyMgmt.NONE);
break;
case SECURITY_WEP:
config.allowedKeyManagement.set(KeyMgmt.NONE);
config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
if (passwordLen != 0) {
// WEP-40, WEP-104, and 256-bit WEP (WEP-232?)
if ((passwordLen == 10 || passwordLen == 26 || passwordLen == 58) && password.matches("[0-9A-Fa-f]*")) {
config.wepKeys[0] = password;
} else {
config.wepKeys[0] = '"' + password + '"';
}
}
break;
case SECURITY_PSK:
config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
if (passwordLen != 0) {
if (password.matches("[0-9A-Fa-f]{64}")) {
config.preSharedKey = password;
} else {
config.preSharedKey = '"' + password + '"';
}
}
break;
case SECURITY_EAP:
config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
// config.eap.setValue((String)
// mEapMethodSpinner.getSelectedItem());
//
// config.phase2.setValue((mPhase2Spinner.getSelectedItemPosition()
// == 0) ? "" :
// "auth=" + mPhase2Spinner.getSelectedItem());
// config.ca_cert.setValue((mEapCaCertSpinner.getSelectedItemPosition()
// == 0) ? "" :
// KEYSTORE_SPACE + Credentials.CA_CERTIFICATE +
// (String) mEapCaCertSpinner.getSelectedItem());
// config.client_cert.setValue((mEapUserCertSpinner.getSelectedItemPosition()
// == 0) ?
// "" : KEYSTORE_SPACE + Credentials.USER_CERTIFICATE +
// (String) mEapUserCertSpinner.getSelectedItem());
// config.private_key.setValue((mEapUserCertSpinner.getSelectedItemPosition()
// == 0) ?
// "" : KEYSTORE_SPACE + Credentials.USER_PRIVATE_KEY +
// (String) mEapUserCertSpinner.getSelectedItem());
// config.identity.setValue((mEapIdentityView.length() == 0) ? "" :
// mEapIdentityView.getText().toString());
// config.anonymous_identity.setValue((mEapAnonymousView.length() ==
// 0) ? "" :
// mEapAnonymousView.getText().toString());
// if (mPasswordView.length() != 0) {
// config.password.setValue(mPasswordView.getText().toString());
// }
break;
default:
LogBridge.d(TAG, "Invalid security type: " + sec);
}
// config.proxySettings = mProxySettings;
// config.ipAssignment = mIpAssignment;
// config.linkProperties = new LinkProperties(mLinkProperties);
}
private static PskType getPskType(ScanResult result) {
boolean wpa = result.capabilities.contains("WPA-PSK");
boolean wpa2 = result.capabilities.contains("WPA2-PSK");
if (wpa2 && wpa) {
return PskType.WPA_WPA2;
} else if (wpa2) {
return PskType.WPA2;
} else if (wpa) {
return PskType.WPA;
} else {
LogBridge.d(TAG, "Received abnormal flag string: " + result.capabilities);
return PskType.UNKNOWN;
}
}
#Override
public String getDisplaySecirityString(final ScanResult scanResult) {
final int security = getSecurity(scanResult);
if (security == SECURITY_PSK) {
switch (getPskType(scanResult)) {
case WPA:
return "WPA";
case WPA_WPA2:
case WPA2:
return "WPA2";
default:
return "?";
}
} else {
switch (security) {
case SECURITY_NONE:
return "OPEN";
case SECURITY_WEP:
return "WEP";
case SECURITY_EAP:
return "EAP";
}
}
return "?";
}
#Override
public boolean isOpenNetwork(String security) {
return String.valueOf(SECURITY_NONE).equals(security);
}
}
And
public abstract class ConfigurationSecurities {
/**
* #return The security of a given {#link WifiConfiguration}.
*/
public abstract String getWifiConfigurationSecurity(WifiConfiguration wifiConfig);
/**
* #return The security of a given {#link ScanResult}.
*/
public abstract String getScanResultSecurity(ScanResult scanResult);
/**
* Fill in the security fields of WifiConfiguration config.
*
* #param config
* The object to fill.
* #param security
* If is OPEN, password is ignored.
* #param password
* Password of the network if security is not OPEN.
*/
public abstract void setupSecurity(WifiConfiguration config, String security, final String password);
public abstract String getDisplaySecirityString(final ScanResult scanResult);
public abstract boolean isOpenNetwork(final String security);
public static ConfigurationSecurities newInstance() {
// if (Version.SDK < 8) {
// return new ConfigurationSecuritiesOld();
// } else {
return new ConfigurationSecuritiesV8();
// }
}
}

Android : To shift the common code of all activities to a base class.. the application crashes

I have the following BaseClass:
public class BaseClass extends Activity implements MusicUtils.Defs,
View.OnTouchListener, View.OnLongClickListener {
private static final int USE_AS_RINGTONE = CHILD_MENU_BASE;
private boolean mOneShot = false;
private boolean mSeeking = false;
private boolean mDeviceHasDpad;
private long mStartSeekenter code herePos = 0;
private long mLastSeekEventTime;
private IMediaPlaybackService mService = null;
private RepeatingImageButton mPrevButton;
private ImageButton mPauseButton;
private RepeatingImageButton mNextButton;
private Worker mAlbumArtWorker;
private AlbumArtHandler mAlbumArtHandler;
private Toast mToast;
private int mTouchSlop;
private ServiceToken mToken;
public BaseClass() {
}
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
mAlbumArtWorker = new Worker("album art worker");
mAlbumArtHandler = new AlbumArtHandler(mAlbumArtWorker.getLooper());
mCurrentTime = (TextView) findViewById(R.id.currenttime);
mTotalTime = (TextView) findViewById(R.id.totaltime);
mPrevButton = (RepeatingImageButton) findViewById(R.id.prev);
mPrevButton.setOnClickListener(mPrevListener);
mPrevButton.setRepeatListener(mRewListener, 260);
mPauseButton = (ImageButton) findViewById(R.id.pause);
mPauseButton.requestFocus();
mPauseButton.setOnClickListener(mPauseListener);
mNextButton = (RepeatingImageButton) findViewById(R.id.next);
mNextButton.setOnClickListener(mNextListener);
mNextButton.setRepeatListener(mFfwdListener, 260);
seekmethod = 1;
mDeviceHasDpad = (getResources().getConfiguration().navigation ==
Configuration.NAVIGATION_DPAD);
if (icicle != null) {
mOneShot = icicle.getBoolean("oneshot");
} else {
mOneShot = getIntent().getBooleanExtra("oneshot", false);
}
mTouchSlop = ViewConfiguration.get(BaseClass.this).getScaledTouchSlop();
}
Handler mLabelScroller = new Handler() {
#Override
public void handleMessage(Message msg) {
TextView tv = (TextView) msg.obj;
int x = tv.getScrollX();
x = x * 3 / 4;
tv.scrollTo(x, 0);
if (x == 0) {
tv.setEllipsize(TruncateAt.END);
} else {
Message newmsg = obtainMessage(0, tv);
mLabelScroller.sendMessageDelayed(newmsg, 15);
}
}
};
Cursor c = MusicUtils.query(this, ContentUris.withAppendedId(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, audioid),
new String[] { MediaStore.Audio.Media.IS_MUSIC }, null,
null,
null);
boolean ismusic = true;
if (c != null) {
if (c.moveToFirst()) {
ismusic = c.getInt(0) != 0;
}
c.close();
}
if (!ismusic) {
return false;
}
boolean knownartist = (artist != null)
&& !MediaStore.UNKNOWN_STRING.equals(artist);
boolean knownalbum = (album != null)
&& !MediaStore.UNKNOWN_STRING.equals(album);
title = getString(R.string.mediasearch, title);
Intent i = new Intent();
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setAction(MediaStore.INTENT_ACTION_MEDIA_SEARCH);
i.putExtra(SearchManager.QUERY, query);
if (knownartist) {
i.putExtra(MediaStore.EXTRA_MEDIA_ARTIST, artist);
}
if (knownalbum) {
i.putExtra(MediaStore.EXTRA_MEDIA_ALBUM, album);
}
i.putExtra(MediaStore.EXTRA_MEDIA_TITLE, song);
i.putExtra(MediaStore.EXTRA_MEDIA_FOCUS, mime);
startActivity(Intent.createChooser(i, title));
return true;
}
private OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
public void onStartTrackingTouch(SeekBar bar) {
mLastSeekEventTime = 0;
mFromTouch = true;
}
public void onProgressChanged(SeekBar bar, int progress,
boolean fromuser) {
if (!fromuser || (mService == null))
return;
long now = SystemClock.elapsedRealtime();
if ((now - mLastSeekEventTime) > 250) {
mLastSeekEventTime = now;
updateTrackInfo();
mPosOverride = mDuration * progress / 1000;
try {
mService.seek(mPosOverride);
} catch (RemoteException ex) {
}
// trackball event, allow progress updates
if (!mFromTouch) {
refreshNow();
mPosOverride = -1;
}
}
}
private View.OnClickListener mPauseListener = new View.OnClickListener() {
public void onClick(View v) {
doPauseResume();
}
};
private View.OnClickListener mPrevListener = new View.OnClickListener() {
public void onClick(View v) {
if (mService == null)
return;
try {
if (mService.position() < 2000) {
mService.prev();
} else {
mService.seek(0);
mService.play();
}
} catch (RemoteException ex) {
}
}
};
#Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
try {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_LEFT:
if (!useDpadMusicControl()) {
break;
}
if (mService != null) {
if (!mSeeking && mStartSeekPos >= 0) {
mPauseButton.requestFocus();
if (mStartSeekPos < 1000) {
mService.prev();
} else {
mService.seek(0);
}
} else {
scanBackward(-1,
event.getEventTime() -
event.getDownTime());
mPauseButton.requestFocus();
mStartSeekPos = -1;
}
}
mSeeking = false;
mPosOverride = -1;
return true;
case KeyEvent.KEYCODE_DPAD_RIGHT:
if (!useDpadMusicControl()) {
break;
}
if (mService != null) {
if (!mSeeking && mStartSeekPos >= 0) {
mPauseButton.requestFocus();
mService.next();
} else {
scanForward(-1,
event.getEventTime() -
event.getDownTime());
mPauseButton.requestFocus();
mStartSeekPos = -1;
}
}
mSeeking = false;
mPosOverride = -1;
return true;
}
} catch (RemoteException ex) {
}
return super.onKeyUp(keyCode, event);
}
private boolean useDpadMusicControl() {
if (mDeviceHasDpad
&& (mPrevButton.isFocused() || mNextButton.isFocused()
|| mPauseButton
.isFocused())) {
return true;
}
return false;
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
int repcnt = event.getRepeatCount();
if ((seekmethod == 0) ? seekMethod1(keyCode) : seekMethod2(keyCode))
return true;
switch (keyCode) {
/*
* // image scale case KeyEvent.KEYCODE_Q: av.adjustParams(-0.05, 0.0,
* 0.0, 0.0, 0.0,-1.0); break; case KeyEvent.KEYCODE_E: av.adjustParams(
* 0.05, 0.0, 0.0, 0.0, 0.0, 1.0); break; // image translate case
* KeyEvent.KEYCODE_W: av.adjustParams( 0.0, 0.0,-1.0, 0.0, 0.0, 0.0);
* break; case KeyEvent.KEYCODE_X: av.adjustParams( 0.0, 0.0, 1.0, 0.0,
* 0.0, 0.0); break; case KeyEvent.KEYCODE_A: av.adjustParams( 0.0,-1.0,
* 0.0, 0.0, 0.0, 0.0); break; case KeyEvent.KEYCODE_D: av.adjustParams(
* 0.0, 1.0, 0.0, 0.0, 0.0, 0.0); break; // camera rotation case
* KeyEvent.KEYCODE_R: av.adjustParams( 0.0, 0.0, 0.0, 0.0, 0.0,-1.0);
* break; case KeyEvent.KEYCODE_U: av.adjustParams( 0.0, 0.0, 0.0, 0.0,
* 0.0, 1.0); break; // camera translate case KeyEvent.KEYCODE_Y:
* av.adjustParams( 0.0, 0.0, 0.0, 0.0,-1.0, 0.0); break; case
* KeyEvent.KEYCODE_N: av.adjustParams( 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
* break; case KeyEvent.KEYCODE_G: av.adjustParams( 0.0, 0.0, 0.0,-1.0,
* 0.0, 0.0); break; case KeyEvent.KEYCODE_J: av.adjustParams( 0.0, 0.0,
* 0.0, 1.0, 0.0, 0.0); break;
*/
case KeyEvent.KEYCODE_SLASH:
seekmethod = 1 - seekmethod;
return true;
case KeyEvent.KEYCODE_DPAD_LEFT:
if (!useDpadMusicControl()) {
break;
}
if (!mPrevButton.hasFocus()) {
mPrevButton.requestFocus();
}
scanBackward(repcnt, event.getEventTime() -
event.getDownTime());
return true;
case KeyEvent.KEYCODE_DPAD_RIGHT:
if (!useDpadMusicControl()) {
break;
}
if (!mNextButton.hasFocus()) {
mNextButton.requestFocus();
}
scanForward(repcnt, event.getEventTime() - event.getDownTime());
return true;
case KeyEvent.KEYCODE_S:
toggleShuffle();
return true;
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_SPACE:
doPauseResume();
return true;
}
return super.onKeyDown(keyCode, event);
}
private void scanBackward(int repcnt, long delta) {
if (mService == null)
return;
try {
if (repcnt == 0) {
mStartSeekPos = mService.position();
mLastSeekEventTime = 0;
mSeeking = false;
} else {
mSeeking = true;
if (delta < 5000) {
// seek at 10x speed for the first 5 seconds
delta = delta * 10;
} else {
// seek at 40x after that
delta = 50000 + (delta - 5000) * 40;
}
long newpos = mStartSeekPos - delta;
if (newpos < 0) {
// move to previous track
mService.prev();
long duration = mService.duration();
mStartSeekPos += duration;
newpos += duration;
}
if (((delta - mLastSeekEventTime) > 250) || repcnt < 0)
{
mService.seek(newpos);
mLastSeekEventTime = delta;
}
if (repcnt >= 0) {
mPosOverride = newpos;
} else {
mPosOverride = -1;
}
refreshNow();
}
} catch (RemoteException ex) {
}
}
private void scanForward(int repcnt, long delta) {
if (mService == null)
return;
try {
if (repcnt == 0) {
mStartSeekPos = mService.position();
mLastSeekEventTime = 0;
mSeeking = false;
} else {
mSeeking = true;
if (delta < 5000) {
// seek at 10x speed for the first 5 seconds
delta = delta * 10;
} else {
// seek at 40x after that
delta = 50000 + (delta - 5000) * 40;
}
long newpos = mStartSeekPos + delta;
long duration = mService.duration();
if (newpos >= duration) {
// move to next track
mService.next();
mStartSeekPos -= duration; // is OK to go
negative
newpos -= duration;
}
if (((delta - mLastSeekEventTime) > 250) || repcnt < 0) {
mService.seek(newpos);
mLastSeekEventTime = delta;
}
if (repcnt >= 0) {
mPosOverride = newpos;
} else {
mPosOverride = -1;
}
refreshNow();
}
} catch (RemoteException ex) {
}
}
private void doPauseResume() {
try {
if (mService != null) {
if (mService.isPlaying()) {
mService.pause();
} else {
mService.play();
}
updateTrackInfo();
refreshNow();
setPauseButtonImage();
}
} catch (RemoteException ex) {
}
}
private void toggleShuffle() {
if (mService == null) {
return;
}
try {
int shuffle = mService.getShuffleMode();
if (shuffle == MediaPlaybackService.SHUFFLE_NONE) {
mService.setShuffleMode(MediaPlaybackService.SHUFFLE_NORMAL);
if (mService.getRepeatMode() ==
MediaPlaybackService.REPEAT_CURRENT) {
mService.setRepeatMode(MediaPlaybackService.REPEAT_ALL);
}
showToast(R.string.shuffle_on_notif);
} else if (shuffle == MediaPlaybackService.SHUFFLE_NORMAL
|| shuffle == MediaPlaybackService.SHUFFLE_AUTO) {
mService.setShuffleMode(MediaPlaybackService.SHUFFLE_NONE);
showToast(R.string.shuffle_off_notif);
} else {
Log.e("MediaPlaybackActivity", "Invalid shuffle mode: "
+ shuffle);
}
} catch (RemoteException ex) {
}
}
private void cycleRepeat() {
if (mService == null) {
return;
}
try {
int mode = mService.getRepeatMode();
if (mode == MediaPlaybackService.REPEAT_NONE) {
mService.setRepeatMode(MediaPlaybackService.REPEAT_ALL);
showToast(R.string.repeat_all_notif);
} else if (mode == MediaPlaybackService.REPEAT_ALL) {
mService.setRepeatMode(MediaPlaybackService.REPEAT_CURRENT);
if (mService.getShuffleMode() != MediaPlaybackService.SHUFFLE_NONE) {
mService.setShuffleMode(MediaPlaybackService.SHUFFLE_NONE);
}
showToast(R.string.repeat_current_notif);
} else {
mService.setRepeatMode(MediaPlaybackService.REPEAT_NONE);
showToast(R.string.repeat_off_notif);
}
} catch (RemoteException ex) {
}
}
private void showToast(int resid) {
if (mToast == null) {
mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT);
}
mToast.setText(resid);
mToast.show();
}
private void startPlayback() {
if (mService == null)
return;
Intent intent = getIntent();
String filename = "";
Uri uri = intent.getData();
if (uri != null && uri.toString().length() > 0) {
// If this is a file:// URI, just use the path directly instead
// of going through the open-from-filedescriptor codepath.
String scheme = uri.getScheme();
if ("file".equals(scheme)) {
filename = uri.getPath();
} else {
filename = uri.toString();
}
try {
if (!ContentResolver.SCHEME_CONTENT.equals(scheme)
|| !MediaStore.AUTHORITY.equals(uri.getAuthority())) {
mOneShot = true;
}
mService.stop();
mService.openFile(filename, mOneShot);
mService.play();
setIntent(new Intent());
} catch (Exception ex) {
Log.d("MediaPlaybackActivity", "couldn't start playback: " + ex);
}
}
updateTrackInfo();
long next = refreshNow();
queueNextRefresh(next);
}
private ServiceConnection osc = new ServiceConnection() {
public void onServiceConnected(ComponentName classname, IBinder obj) {
mService = IMediaPlaybackService.Stub.asInterface(obj);
startPlayback();
try {
// Assume something is playing when the service says it is,
// but also if the audio ID is valid but the service is paused.
if (mService.getAudioId() >= 0 || mService.isPlaying()
|| mService.getPath() != null) {
// something is playing now, we're done
setPauseButtonImage();
return;
}
} catch (RemoteException ex) {
}
// Service is dead or not playing anything. If we got here as part
// of a "play this file" Intent, exit. Otherwise go to the Music
// app start screen.
if (getIntent().getData() == null) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClass(BaseClass.this, MusicBrowserActivity.class);
startActivity(intent);
}
finish();
}
public void onServiceDisconnected(ComponentName classname) {
mService = null;
}
};
private void setPauseButtonImage() {
try {
if (mService != null && mService.isPlaying()) {
mPauseButton
.setImageResource(android.R.drawable.ic_media_pause);
} else {
mPauseButton.setImageResource(android.R.drawable.ic_media_play);
}
} catch (RemoteException ex) {
}
}
private TextView mCurrentTime;
private TextView mTotalTime;
private long mPosOverride = -1;
private boolean mFromTouch = false;
private long mDuration;
private int seekmethod;
private boolean paused;
private static final int REFRESH = 1;
private static final int QUIT = 2;
private static final int GET_ALBUM_ART = 3;
private static final int ALBUM_ART_DECODED = 4;
private void queueNextRefresh(long delay) {
if (!paused) {
Message msg = mHandler.obtainMessage(REFRESH);
mHandler.removeMessages(REFRESH);
mHandler.sendMessageDelayed(msg, delay);
}
}
private long refreshNow() {
if (mService == null)
return 500;
try {
long pos = mPosOverride < 0 ? mService.position() : mPosOverride;
long remaining = 1000 - (pos % 1000);
if ((pos >= 0) && (mService.duration() > 0)) {
mCurrentTime.setText(MusicUtils
.makeTimeString(this, pos / 1000));
if (mService.isPlaying()) {
mCurrentTime.setVisibility(View.VISIBLE);
} else {
// blink the counter
int vis = mCurrentTime.getVisibility();
mCurrentTime
.setVisibility(vis == View.INVISIBLE ? View.VISIBLE
: View.INVISIBLE);
remaining = 500;
}
} else {
mCurrentTime.setText("--:--");
}
// return the number of milliseconds until the next full second, so
// the counter can be updated at just the right time
return remaining;
} catch (RemoteException ex) {
}
return 500;
}
private final Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case REFRESH:
updateTrackInfo();
long next = refreshNow();
queueNextRefresh(next);
break;
case QUIT:
// This can be moved back to onCreate once the bug that prevents
// Dialogs from being started from onCreate/onResume is fixed.
new AlertDialog.Builder(BaseClass.this)
.setTitle(R.string.service_start_error_title)
.setMessage(R.string.service_start_error_msg)
.setPositiveButton(R.string.service_start_error_button,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
finish();
}
}).setCancelable(false).show();
break;
default:
break;
}
}
};
private BroadcastReceiver mStatusListener = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(MediaPlaybackService.META_CHANGED)) {
// redraw the artist/title info and
// set new max for progress bar
updateTrackInfo();
setPauseButtonImage();
queueNextRefresh(1);
} else if (action.equals(MediaPlaybackService.PLAYBACK_COMPLETE)) {
if (mOneShot) {
finish();
} else {
setPauseButtonImage();
}
} else if (action.equals(MediaPlaybackService.PLAYSTATE_CHANGED)) {
setPauseButtonImage();
}
}
};
private static class AlbumSongIdWrapper {
public long albumid;
public long songid;
AlbumSongIdWrapper(long aid, long sid) {
albumid = aid;
songid = sid;
}
}
private void updateTrackInfo() {
if (mService == null) {
return;
}
try {
String path = mService.getPath();
if (path == null) {
finish();
return;
}
long songid = mService.getAudioId();
if (songid < 0 && path.toLowerCase().startsWith("http://")) {
// Once we can get album art and meta data from MediaPlayer, we
// can show that info again when streaming.
mAlbumArtHandler.removeMessages(GET_ALBUM_ART);
mAlbumArtHandler.obtainMessage(GET_ALBUM_ART,
new AlbumSongIdWrapper(-1, -1)).sendToTarget();
} else {
String artistName = mService.getArtistName();
if (MediaStore.UNKNOWN_STRING.equals(artistName)) {
artistName = getString(R.string.unknown_artist_name);
}
String albumName = mService.getAlbumName();
long albumid = mService.getAlbumId();
if (MediaStore.UNKNOWN_STRING.equals(albumName)) {
albumName = getString(R.string.unknown_album_name);
albumid = -1;
}
mAlbumArtHandler.removeMessages(GET_ALBUM_ART);
mAlbumArtHandler.obtainMessage(GET_ALBUM_ART,
new AlbumSongIdWrapper(albumid, songid)).sendToTarget();
}
mDuration = mService.duration();
mTotalTime.setText(MusicUtils
.makeTimeString(this, mDuration / 1000));
} catch (RemoteException ex) {
finish();
}
}
public class AlbumArtHandler extends Handler {
private long mAlbumId = -1;
public AlbumArtHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
long albumid = ((AlbumSongIdWrapper) msg.obj).albumid;
long songid = ((AlbumSongIdWrapper) msg.obj).songid;
if (msg.what == GET_ALBUM_ART
&& (mAlbumId != albumid || albumid < 0)) {
// while decoding the new image, show the default album art
Message numsg = mHandler.obtainMessage(ALBUM_ART_DECODED, null);
mHandler.removeMessages(ALBUM_ART_DECODED);
mHandler.sendMessageDelayed(numsg, 300);
Bitmap bm = MusicUtils.getArtwork(BaseClass.this, songid,
albumid);
if (bm == null) {
bm = MusicUtils.getArtwork(BaseClass.this, songid, -1);
albumid = -1;
}
if (bm != null) {
numsg = mHandler.obtainMessage(ALBUM_ART_DECODED, bm);
mHandler.removeMessages(ALBUM_ART_DECODED);
mHandler.sendMessage(numsg);
}
mAlbumId = albumid;
}
}
}
public static class Worker implements Runnable {
private final Object mLock = new Object();
private Looper mLooper;
/**
* Creates a worker thread with the given name. The thread then runs a
* {#link android.os.Looper}.
*
* #param name
* A name for the new thread
*/
Worker(String name) {
Thread t = new Thread(null, this, name);
t.setPriority(Thread.MIN_PRIORITY);
t.start();
synchronized (mLock) {
while (mLooper == null) {
try {
mLock.wait();
} catch (InterruptedException ex) {
}
}
}
}
public Looper getLooper() {
return mLooper;
}
public void run() {
synchronized (mLock) {
Looper.prepare();
mLooper = Looper.myLooper();
mLock.notifyAll();
}
Looper.loop();
}
public void quit() {
mLooper.quit();
}
}
}
And I want to extend this Class.. But the program crashes showing null pointer exception at this base class.. The base class doesn't have any content view and it points to the buttons (ex.previous and next button), and shows null pointer.. please guide me to solve this problem.
set contentview in the child class and parent class can access it.

Categories

Resources