I am developing something like X11 server for Android and I need some help.
I found out that applications like bVNC and Microsoft Remote Desktop client can intercept Super, Alt-Tab, Alt-F4 and almost all keyboard events.
I tried to guess what exactly is done to achieve this but failed.
I found out that after running bVNC on my phone I can run my own com.iiordanov.bVNC.RemoteCanvasActivity with simple View.OnKeyListener and focused View receives all the events I need without system response (i.e. no recents menu on Alt-Tab). But when I change package name or class name I loose this ability.
Is there anyone who can help with this please?
package com.iiordanov.bVNC;
import android.os.Build;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnKeyListener;
import android.view.WindowManager;
import android.widget.TextView;
public class RemoteCanvasActivity extends AppCompatActivity implements OnKeyListener {
private final static String TAG = "RemoteCanvas";
TextView log;
#Override
public void onCreate(Bundle b) {
super.onCreate(b);
log = new TextView(this);
setContentView(log);
log.setSingleLine(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
log.setDefaultFocusHighlightEnabled(false);
}
log.setOnKeyListener(this);
log.setFocusableInTouchMode(true);
log.setDrawingCacheEnabled(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
log.setFocusedByDefault(true);
}
log.requestFocus();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
#Override
public boolean onKey(View v, int keyCode, KeyEvent evt) {
if (log != null) {
log.append("Got keycode " + keyCode + " " + evt.getAction() + "\n");
final int scrollAmount = log.getLayout().getLineTop(log.getLineCount()) - log.getHeight();
// if there is no need to scroll, scrollAmount will be <=0
if (scrollAmount > 0)
log.scrollTo(0, scrollAmount);
else
log.scrollTo(0, 0);
}
return true;
}
}
117 is KeyEvent.KEYCODE_META_LEFT.
25 is KeyEvent.KEYCODE_VOLUME_DOWN.
Thank you very much.
Related
I am a beginner to coding in general and am working with Java in Android Studio. I am working on an app and I cannot get my if/else statement to work properly. Right now it is accepting any number. Can someone please let me know what I am doing wrong here?
import androidx.appcompat.app.AppCompatActivity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.widget.ImageView;
import android.widget.TextView;
import java.text.DecimalFormat;
public class Cost extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cost);
TextView totalCost = (TextView)findViewById(R.id.txtCost);
ImageView image = (ImageView)findViewById(R.id.imgRental);
SharedPreferences sharedPref =
PreferenceManager.getDefaultSharedPreferences(this);
float floatTruckSize = sharedPref.getFloat("key1", 0);
float floatMiles = sharedPref.getFloat("key2", 0);
float floatCost;
if (floatTruckSize == 10) {
floatTruckSize = (float) 19.95;
image.setImageResource(R.drawable.tenfoot);
} else if (floatTruckSize == 17) {
floatTruckSize = (float) 29.95;
image.setImageResource(R.drawable.seventeenfoot);
} else if (floatTruckSize == 26) {
floatTruckSize = (float) 39.95;
image.setImageResource(R.drawable.twentysixfoot);
} else {
totalCost.setText("Enter 10, 17, or 26 foot truck rental");
}
floatCost = (float) (floatTruckSize * (floatMiles * .99));
DecimalFormat currency = new DecimalFormat("$###,###.##");
totalCost.setText("Total cost for 1-day truck rental " +
currency.format(floatCost));
}
}
In my Android Client App I'm trying to send virtual joystick coordinates over socket from client(Android) to a server(Arduino).I'm Tray Codding a thread 't' in main activity containing a socket 's', to send x,y Coordinate to arduino Server.
the JoystickView Class give me 'x' and 'y' when I move the joystick.
this will be done after user Click Connect button,
'x' is from 0 to 255, also 'y' but to be able to know witch value is 'x' and witch is 'y' in arduino side, I added 255 to y so y will be from 255 to 510.
virtual joy stick provide me with 'x','y' Coordinate Stored in public variables 'xxx' and 'yyy'.
Linked a Connect Button with thread 't, Created I socket 's' to send 'x','y' to server.
**my Question: can my Code works with the Arduino and Can I get x,y in Arduino Side ?, also I couldn't put thread 't' in "public void onClick(View v)" function. its the second problem :( **
package com.ravensoft.daniel.joysticktest;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.io.DataOutputStream;
public class MainActivity extends AppCompatActivity implements
JoystickView.JoystickListener{
TextView x;
TextView y;
public float xxx=0;//bublic var will Contain x value from virtual
joystick
public float yyy=0;//bublic var will Contain x value from virtual
joystick
EditText txt_IP;//arduino ip
EditText txt_PORT;//arduino port
private volatile Socket socket = null;
private boolean connectionOk = false;
private Button buttonDisconnect; //button for disconnect connection
private Button buttonConnect;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
JoystickView joystick = new JoystickView(this);
setContentView(R.layout.activity_main);
buttonConnect = findViewById(R.id.buttonConnect);
buttonDisconnect = findViewById(R.id.buttonDisconnect);
JoystickView joystic =findViewById(R.id.joystick);
txt_IP=(EditText)findViewById(R.id.editText_IP);
txt_PORT=(EditText)findViewById(R.id.editText_PORT);
buttonConnect.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View v) {
}
});
buttonDisconnect.setEnabled(false);
buttonConnect.setEnabled(true);
}
Thread t=new Thread(new Runnable() {
#Override
public void run() {
try {
Socket s = new Socket(txt_IP.getText().toString(),Integer.parseInt(txt_PORT.getText().toString() ));
s.connect(new InetSocketAddress(txt_IP.getText().toString(), Integer.parseInt(txt_PORT.getText().toString() )), 50);
if(s == null)System.out.println("SOCKET NULL");
DataOutputStream DataOut = new DataOutputStream(s.getOutputStream());
String message= Float.toString(xxx+256);
byte[] msgBuffer=message.getBytes();
String message2= Float.toString(yyy);
byte[] msgBuffer2=message2.getBytes();
try {
DataOut.write(msgBuffer);
DataOut.write(msgBuffer2);
}catch (IOException e){
}
DataOut.flush();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
#Override
public void onJoystickMoved( float xPercent, float yPercent) {
x = (TextView) findViewById(R.id.x_value);
x.setText(Float.toString(xPercent));
y = (TextView) findViewById(R.id.y);
y.setText(Float.toString(-yPercent));
xxx=xPercent;
yyy=yPercent;
Log.d("Right Joystick", "X percent: " + xPercent + " Y percent: " + yPercent);
}}
I have search now for hours through the internet and have found nothing substantial so far. The thing that I want to do is a multi choice preference view, that disables the last item and reenables it, if it is not alone anymore.
I through so far about taking the super class force read the private variables in there to write my own onPrepareDialogBuilder(AlertDialog.Builder builder). Which is configuring its own OnMultiChoiceClickListener that jumps in, in the moment where has only one item left. The problem here is, that I use a bad practice force read of a private variable and that I have so far no idea how to get the checkbox item and how to disable it. But I think looking even deeper into the Android SDK will solve this problem.
At the end, if nothing works, solving the problem with doing an overwrite the OnPreferenceChangeListener to display a toast if the user has less than one item selected. But user friendliness is a high value, that needs to be earned and that often isn't easy.
Thx.
import android.content.Context;
import android.preference.MultiSelectListPreference;
import android.util.AttributeSet;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import georg.com.flironetest_01.Variables.Units;
/**
* Created by Georg on 16/03/16.
*/
public class UnitMultipleSelectorPreference extends MultiSelectListPreference {
public UnitMultipleSelectorPreference(Context context, AttributeSet attrs) {
super(context, attrs);
List<CharSequence> humanU = new ArrayList<>();
List<CharSequence> machineU = new ArrayList<>();
Units[] all = Units.values(); // Units is a enum with a rewriten to string statement.
for (Units elem : all) {
humanU.add(elem.toString());
machineU.add(elem.name());
}
setEntries(humanU.toArray(new CharSequence[humanU.size()]));
setEntryValues(machineU.toArray(new CharSequence[machineU.size()]));
Set<String> mU = new HashSet<>();
mU.add(Units.C.name());
mU.add(Units.K.name());
setDefaultValue(mU);
}
}
Okay. To answer my own question here after the motto "self is the man": I ended up with programming my own preference panel. Below is the code. If somebody likes to look over it and give some times how to make it even more stable: feel free.
But to sum up what I did: I created my own ArrayAdapter. But DialogPreference didn't allowed me to create my own multi selector. You need to change the final dialog fragment to create a working multi selector list (see here: https://stackoverflow.com/a/17907379/5759814). That is not an easy task if you work with the DialogPreferences. The reason is these few amounts of code:
/**
* Shows the dialog associated with this Preference. This is normally initiated
* automatically on clicking on the preference. Call this method if you need to
* show the dialog on some other event.
*
* #param state Optional instance state to restore on the dialog
*/
protected void showDialog(Bundle state) {
Context context = getContext();
mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE;
mBuilder = new AlertDialog.Builder(context)
.setTitle(mDialogTitle)
.setIcon(mDialogIcon)
.setPositiveButton(mPositiveButtonText, this)
.setNegativeButton(mNegativeButtonText, this);
View contentView = onCreateDialogView();
if (contentView != null) {
onBindDialogView(contentView);
mBuilder.setView(contentView);
} else {
mBuilder.setMessage(mDialogMessage);
}
onPrepareDialogBuilder(mBuilder);
getPreferenceManager().registerOnActivityDestroyListener(this);
// Create the dialog
final Dialog dialog = mDialog = mBuilder.create();
if (state != null) {
dialog.onRestoreInstanceState(state);
}
if (needInputMethod()) {
requestInputMethod(dialog);
}
dialog.setOnDismissListener(this);
dialog.show();
}
As you can see here is a method triggered to change my dialog builder with onPrepareDialogBuilder, but it doesn't seem like that there is any other function triggered afterwards, that would allow me to change the dialog directly after its creation. And the second idea of changing the onPrepareDialogBuilder so that I can init everything there, doesn't really help, because I end up with displayed dialog windows. That lead me to my decision of creating my completely own Preference class. With that decision I loose all those nice prepared functions like onRestoreInstanceState and Co, but I now have an application with a much more persistent flow, that doesn't do any stupid things when I select zero units for my thermal view.
Below the non commented code. I'm sorry, but I think its simple enough for everybody who landing here.
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.preference.Preference;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import georg.com.flironetest_01.Variables.Units;
/**
* Created by Georg on 16/03/16.
*/
public class UnitMultipleSelectorPreference extends Preference implements DialogInterface.OnClickListener, Preference.OnPreferenceClickListener {
String[] human_entries = null;
String[] machine_entries = null;
public SharedPreferences prev;
public UnitMultipleSelectorPreference(Context context, AttributeSet attrs) {
super(context, attrs);
prev = getSharedPreferences();
List<String> humanU = new ArrayList<>();
List<String> machineU = new ArrayList<>();
Units[] all = Units.values();
for (Units elem : all) {
humanU.add(elem.toString());
machineU.add(elem.name());
}
human_entries = humanU.toArray(new String[humanU.size()]);
machine_entries = machineU.toArray(new String[machineU.size()]);
Set<String> mU = new HashSet<>();
mU.add(Units.C.name());
mU.add(Units.K.name());
setDefaultValue(mU);
setOnPreferenceClickListener(this);
}
boolean[] selected = new boolean[0];
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
if (prev == null)
return;
if (human_entries == null || machine_entries == null || human_entries.length != machine_entries.length ) {
throw new IllegalStateException(
"ListPreference requires an entries array and an entryValues array which are both the same length");
}
selected = new boolean[human_entries.length];
for (int i = 0; i < human_entries.length; i++)
selected[i] = prefSet.contains(machine_entries[i]);
String[] stringObj = new String[human_entries.length];
int i = 0;
for(CharSequence ch : human_entries)
stringObj[i++] = ch.toString();
builder.setAdapter(new MyAdapter(getContext(), android.R.layout.simple_list_item_multiple_choice, stringObj), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
AlertDialog mDialog = builder.create();
mDialog.getListView().setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
mDialog.getListView().setItemsCanFocus(false);
mDialog.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// Manage selected items here
ListView mParent = (ListView)parent;
if (mParent.getCheckedItemCount() >= 1)
selected[position] = mParent.isItemChecked(position);
if (mParent.getCheckedItemCount() == 0)
mParent.setItemChecked(position, true);
}
});
mDialog.show();
i = 0;
for (boolean select : selected)
mDialog.getListView().setItemChecked(i++, select);
}
#Override
public boolean onPreferenceClick(Preference preference) {
AlertDialog.Builder mBuilder = new AlertDialog.Builder(getContext());
mBuilder.setTitle(getTitle())
.setPositiveButton(android.R.string.ok, this)
.setNegativeButton(android.R.string.cancel, this);
onPrepareDialogBuilder(mBuilder);
return true;
}
#Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getContext(), "W:"+which + " | " + Arrays.toString(selected), Toast.LENGTH_SHORT).show();
switch (which) {
case -1:
if (isPersistent()) {
prefSet = new HashSet<>();
for (int i = 0; i < selected.length; i++) {
if (selected[i])
prefSet.add(machine_entries[i]);
}
getEditor().putStringSet(getKey(), prefSet).apply();
Toast.makeText(getContext(), "W:"+which + " | " + getSharedPreferences().getStringSet(getKey(),null).toString(), Toast.LENGTH_SHORT).show();
}
return;
}
}
public class MyAdapter extends ArrayAdapter<String> {
public MyAdapter(Context context, int textViewResourceId, String[] objects) {
super(context, textViewResourceId, objects);
}
#Override
public boolean isEnabled(int n) {
return true;
}
}
Set<String> prefSet;
#Override
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
super.onSetInitialValue(restorePersistedValue, defaultValue);
prev = getSharedPreferences();
if(restorePersistedValue) {
prefSet = prev.getStringSet(getKey(), new HashSet<String>());
} else {
try {
prefSet = (Set<String>)defaultValue;
if(isPersistent())
getEditor().putStringSet(getKey(), prefSet);
} catch (ClassCastException e) {
Log.e("ERROR_CAST", "Error casting the default value to Set<String>.");
}
}
}
}
A really simple solution is to set a setOnPreferenceChangeListener and just return false if the new value would be empty.
All of the code is put into onCreatePreferences.
MultiSelectListPreference infoPreference = findPreference("information");
infoPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (size(newValue) == 0){
return false;
}
return true;
}
});
How can I add multiple showcaseviews to my layout...
I've tried this:
import com.github.amlcurran.showcaseview.sample.R;
import android.annotation.TargetApi;
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
public class MultipleShowcaseSampleActivity extends Activity {
private static final float SHOWCASE_KITTEN_SCALE = 1.2f;
private static final float SHOWCASE_LIKE_SCALE = 0.5f;
//ShowcaseViews mViews;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sample_legacy);
findViewById(R.id.buttonLike).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getApplicationContext(), R.string.like_message, Toast.LENGTH_SHORT).show();
}
});
//mOptions.block = false;
// mViews = new ShowcaseViews(this,
// new ShowcaseViews.OnShowcaseAcknowledged() {
// #Override
// public void onShowCaseAcknowledged(ShowcaseView showcaseView) {
// Toast.makeText(MultipleShowcaseSampleActivity.this, R.string.dismissed_message, Toast.LENGTH_SHORT).show();
// }
// });
// mViews.addView( new ShowcaseViews.ItemViewProperties(R.id.image,
// R.string.showcase_image_title,
// R.string.showcase_image_message,
// SHOWCASE_KITTEN_SCALE));
// mViews.addView( new ShowcaseViews.ItemViewProperties(R.id.buttonLike,
// R.string.showcase_like_title,
// R.string.showcase_like_message,
// SHOWCASE_LIKE_SCALE));
// mViews.show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
enableUp();
}
}
You can see the comment part, When I uncomment Showcaseview cant found those methods so maybe ShowcaseViews missing, anyway I tried to copy and create that class, but still need methods from showcaseview that cant be found.
Help Me.
Update: Ok according the answer below, I have a problem:
mViews = new ShowcaseView(this,
new ShowcaseView.setOnShowcaseEventListener() {
#Override
public void onShowCaseAcknowledged(ShowcaseView showcaseView) {
Toast.makeText(MultipleShowcaseSampleActivity.this, R.string.dismissed_message, Toast.LENGTH_SHORT).show();
}
});
mViews.addView( new ShowcaseView.ItemViewProperties(R.id.image,
R.string.showcase_image_title,
R.string.showcase_image_message,
SHOWCASE_KITTEN_SCALE));
mViews.addView( new ShowcaseView.ItemViewProperties(R.id.buttonLike,
R.string.showcase_like_title,
R.string.showcase_like_message,
SHOWCASE_LIKE_SCALE));
mViews.show();
On new ShowcaseView.setOnShowcaseEventListener() Cannot be resolve to a type
then new ShowcaseView.ItemViewProperties Cannot be resolve to a type too.
The library doesn't have any class called ShowCaseViews. It only has a class ShowCaseView.
If you are following this github example you have to have the class given in the link
EDIT Okay let me try and explain classes
There are 2 classes
ShowcaseView (in the library)
ShowcaseViews (in the example on Github)
You cannot say ShowcaseView.ItemProperties because ShowcaseView doesn't have them. They belong to ShowcaseViews. Hence they cannot be resolved or found.
OnShowcaseEventListener is a whole different class, contained in neither one of these but just exists separately and hence also when you say ShowcaseView.OnShowcaseEventListener it can't be resolved.
Change ShowcaseView.OnShowcaseEventListener to just OnShowcaseEventListener and ShowcaseView.ItemPropertiesto ShowcaseViews.ItemProperties
I'm working on an app that involved comparing to numbers inputted by the user via text box, but wen I put in any if statements the program crashes whenever they are called. Otherwise the program runs just fine without any crashes or errors.
package improvecredit.app.basic;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.text.Editable;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class ImprovrCreditBasicActivity extends Activity {
/** Called when the activity is first created. */
public int minCredScore = 300;
public int maxCredScore = 850;
public int inputScore;
public int idealScore;
public Editable inputString;
public Editable idealString;
public EditText user;
public EditText desired;
public TextView output;
public Button submit;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
user = (EditText) findViewById(R.id.user_text);
desired = (EditText) findViewById(R.id.desired_text);
output = (TextView) findViewById(R.id.output_text);
submit = (Button) findViewById(R.id.submit_button);
//submit.setOnClickListener(new View.OnClickListener());
submit.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//inputString = user.getText();
//idealString = desired.getText();
inputScore = Integer.getInteger(user.getText().toString());
idealScore = Integer.getInteger(desired.getText().toString());
if (inputScore >= 0 && idealScore >= 0){
if (inputScore < minCredScore || idealScore < minCredScore){
output.setText("Invalid Entries");
}
if (inputScore > maxCredScore || idealScore > maxCredScore){
output.setText("Invalid Entries");
}
if (inputScore > idealScore){
output.setText("Nice Credit Score!");
}
if (inputScore < idealScore){
output.setText("For more information on how to improve your credit score, please visit" + "/n" + "http://www.creditscoresandcredit.com/");
}
}
else{
output.setText("Please enter valid credit scores");
}
}
});
}
If someone can point out what may have been done wrong in the code I would really appreciate it.
On first glance, don't use Integer.getInteger(), use Integer.parseInt().
If that doesn't fix it, please include the crash log from the console so we can see exactly what exception is being raised.
I'm betting that there is a null value introduced. If you check for null before using the variables idealScore and inputScore in the If statement, it will avoid this error. Until you paste the error trace, we can only guess for you.