I'm developing a simple app that injects lines on build.prop by executing a shell command. My main problem is that every time I check a toggle that create the function a toast displaying the shell string appear. Is there any way to avoid this? also, if you have any suggestion to clean a bit the code would be appreciated! (First app for me).
Code:
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
// fragment not when container null
if (container == null) {
return null;
}
// inflate view from layout
View v = (LinearLayout)inflater.inflate(R.layout.performance,container,false);
final CheckBox hwdebug = (CheckBox) v.findViewById(R.id.hwDebug);
final String[] mountrw = {"su","-c","mount -o remount,rw /system"};
final String[] enhwdebug1 = {"su","-c","sed -i '/debug.sf.hw=*/d' /system/build.prop"};
final String[] enhwdebug2 = {"su","-c","echo '## Rendering GPU Enabled ##' >> /system/build.prop"};
final String[] enhwdebug3 = {"su","-c","echo debug.sf.hw=1 >> /system/build.prop"};
final String[] dishwdebug1 = {"su","-c","sed -i '/debug.sf.hw=1/d' /system/build.prop"};
final String[] dishwdebug2 = {"su","-c","sed -i '/## Rendering GPU Enabled ##/d' /system/build.prop"};
final SharedPreferences hwdebugpref = this.getActivity().getSharedPreferences("hwdebugck",0);
// GPU Rendering Checkbox
boolean hwdebugck = hwdebugpref.getBoolean("hwdebugck", false);
if (hwdebugck) {
hwdebug.setChecked(true);
} else {
hwdebug.setChecked(false);
}
hwdebug.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if((hwdebug.isChecked())) {
SharedPreferences.Editor editor = hwdebugpref.edit();
editor.putBoolean("hwdebugck", true); // value to store
editor.commit();
ArrayList<String[]> enhwdebug = new ArrayList<String[]>();
enhwdebug.add(mountrw);
enhwdebug.add(enhwdebug1);
enhwdebug.add(enhwdebug2);
enhwdebug.add(enhwdebug3);
for(String[] cmd:enhwdebug){
try {
Runtime.getRuntime().exec(cmd);
} catch (IOException e) {
e.fillInStackTrace();
}
}
} else {
SharedPreferences.Editor editor = hwdebugpref.edit();
editor.putBoolean("hwdebugck", false); // value to store
editor.commit();
ArrayList<String[]> diswdebug = new ArrayList<String[]>();
diswdebug.add(mountrw);
diswdebug.add(dishwdebug1);
diswdebug.add(dishwdebug2);
for(String[] cmd:diswdebug){
try {
Runtime.getRuntime().exec(cmd);
} catch (IOException e) {
e.fillInStackTrace();
}
}
}
}
});
So, my main problem is that su -c show that annoying toast. I tried to pass it to busybox or toolbox but without success since they need to be ran with su.
Thank you!
It is possible , by having the same thread that makes the call to root commands stay and let it always be the only one that handles them.
This way, the toast will only appear the first time you use root operations.
Also, on the end user side, some apps (like super-su) allow to avoid the toast, even per app.
Ok first to answer your question the answer is yes and no.
Easy Answer:
No its not possible using one of the current SU managers like SuperUser or SuperSU you cant. The toast is a safety mechanism. Both apps features to remove the toast for specific apps, but you as a dev can not control this.
Hard Answer:
Yes it is possible, but it would require you compiling your own su binary and using it in place of the su binary already installed. You would need to remove the code that references the current manager (Which ever source you compiled from). Would be recommend to add checks so that ONLY your app can run that binary. This can lead to security risks though and is probably is not a good idea.
I did not look through your code very much but i would say one thing do NOT under any circumstance run SU commands on the UI thread. This is only asking for problems.
Related
In a program I am developing using jcef, I want to allow the camera to be used inside. I am trying to give --enable-media-stream switch for the program that I am building using jcef. I am tried to turn on switch with the following cases:
settings.windowless_rendering_enabled = useOSR;
settings.command_line_args_disabled = false;
String[] args = new String[]{
"--enable-media-stream=true"
// "--enable-media-steam",
// "enable-media-stream", "1"
};
cefApp = CefApp.getInstance(args, settings);
Program gives
[1031/094701.279:INFO:CONSOLE(0)] "Uncaught (in promise) NotAllowedError: Permission denied", source: theUrl
error in every cases.
However, the camera is allowed if I run *.jar app from command line with: "java -jar appName.jar --enable-media-stream" command.
What might be the issue here?
Thanks in advance.
I solved it with next code:
CefApp.addAppHandler(new CefAppHandlerAdapter(null) {
#Override
public void onBeforeCommandLineProcessing(String process_type, CefCommandLine command_line) {
super.onBeforeCommandLineProcessing(process_type, command_line);
if (process_type.isEmpty()) {
command_line.appendSwitchWithValue("enable-media-stream","true");
}
}
});
Basically, what I am trying to do is change the CONTROL_AE_MODE by button click in the app. The user can use AUTO flash(ON_AUTO_FLASH), turn if ON(ON_ALWAYS_FLASH), or OFF(CONTROL_AE_MODE_OFF).
In this example: https://github.com/googlesamples/android-Camera2Basic/blob/master/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.java
Line 818, they set the flash once:
// Use the same AE and AF modes as the preview.
captureBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
setAutoFlash(captureBuilder);
// Orientation
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
CameraCaptureSession.CaptureCallback CaptureCallback
= new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(#NonNull CameraCaptureSession session,
#NonNull CaptureRequest request,
#NonNull TotalCaptureResult result) {
showToast("Saved: " + mFile);
Log.d(TAG, mFile.toString());
unlockFocus();
}
};
mCaptureSession.stopRepeating();
mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
And then builds the CaptureSession at line 840.
Is there a way to change the CONTROL_AE_MODE after the preview is made?
I have tried remaking the session, which kinda worked:
if(flashMode == CameraView.CAMERA_FLASH_ON){
Log.e("CAMERA 2", "FLASH ON");
mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
}else if(flashMode == CameraView.CAMERA_FLASH_OFF){
Log.e("CAMERA 2", "FLASH OFF");
mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
}else if(flashMode == CameraView.CAMERA_FLASH_AUTO){
Log.e("CAMERA 2", "FLASH AUTO");
mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
}
mFlashMode = flashMode;
if (mCameraCaptureSession != null) {
mCameraCaptureSession.close();
mCameraCaptureSession = null;
}
createCameraPreviewSession();
For some reason, CONTROL_AE_MODE_OFF would turn the whole preview black.
I tried looking in the docs for methods to update but haven't found anything.
Any tutorials or docs is much appreciated.
As mentioned by #cyborg86pl when switching flash modes you should not switch CONTROL_AE_MODE . Instead you can switch between FLASH_MODEĀ“s. Here is a working example for my case:
when (currentFlashState) {
FlashState.AUTO -> {
previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH)
}
FlashState.ON -> {
previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON)
previewRequestBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH)
}
FlashState.OFF -> {
previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON)
previewRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF)
}
}
previewRequest = previewRequestBuilder.build()
captureSession.setRepeatingRequest(previewRequest, captureCallback, backgroundHandler)
I don't know why your preview turn black, but you don't need to close capture session manually. From .close() method's docs:
Using createCaptureSession(List , CameraCaptureSession.StateCallback,
Handler) directly without closing is the recommended approach for
quickly switching to a new session, since unchanged target outputs can
be reused more efficiently.
So you can reuse existing CaptureRequest.Builder, set your changed value, build new PreviewRequest and just start new session with this new request, like this:
try {
// Change some capture settings
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
// Build new request (we can't just edit existing one, as it is immutable)
mPreviewRequest = mPreviewRequestBuilder.build();
// Set new repeating request with our changed one
mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
It will be much faster (almost without any visible freeze of preview).
What you want is disabling flash, not auto-exposure (AE), thus you want to use CONTROL_AE_MODE_ON rather than CONTROL_AE_MODE_OFF.
As mentioned in the documentation:
CONTROL_AE_MODE_ON
The camera device's autoexposure routine is active, with no flash control.
How does Lastpass manage this?!
AccessibilityNodeInfo has a setText() method, but I feel like this is a red herring as the docs state,
Note: Cannot be called from an AccessibilityService. This class is made immutable before being delivered to an AccessibilityService.
Another user asked a similar question a while back, but the recent updates to LastPass prove that it is indeed possible.
Set text in AccessibilityNodeInfo
I found some better solution rather than ACTION_PASTE. I feel ACTION_PASTE makes delay and didn't work properly. ACTION_SET_TEXT works fine for me, check with you.
public void pasteText(AccessibilityNodeInfo node, String text) {
Bundle arguments = new Bundle();
arguments.putString(AccessibilityNodeInfoCompat.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
node.performAction(AccessibilityNodeInfoCompat.ACTION_SET_TEXT, arguments);
}
I have figured this out and have it implemented in my app, TapN.
First get the original clipboard contents, save that, copy to the clipboard your content, then paste it, then copy the original content back.
public void inputData(Context c, String data, AccessibilityNodeInfo source) {
try {
String lastClip = clipboard.getPrimaryClip().getItemAt(0).coerceToText(c)
.toString();
} catch (Exception e) {
lastClip = "";
}
Log.d("THE NODE INFO", source.toString());
ClipData clip = ClipData.newPlainText("nfc_input", data);
clipboard.setPrimaryClip(clip);
Log.d("SENDING DATA", Boolean.toString(source.refresh()));
Log.d("SENDING DATA", Boolean.toString(source
.performAction(AccessibilityNodeInfo.ACTION_PASTE)));
ClipData clip = ClipData.newPlainText("nfc_input", lastClip);
clipboard.setPrimaryClip(clip);
}
Ok I'm learning how shell commands work, so I decided to develop a app to send the commands. This is what I got.
moveDirectory.setOnClickListener(new OnClickListener(){
public void onClick(View v)
{
try{
Process send = Runtime.getRunetime().exec(new String[] {"cd /sdcard/music/", "cp pic1 /sdcard/pic1"});
send.waitFor();
} catch (Exception ex){
String toast = null;
Log.i(toast, "Couldn't copy file", ex);
}
}
});
But it isn't working, the first command is working, but not the second one. What should I add to it?
Thanks
EDIT: forgot to add the send.waitFor(); line
Use normal command delimeter ;
moveDirectory.setOnClickListener(new OnClickListener(){
public void onClick(View v)
{
try{
Process send = Runtime.getRunetime().exec(new String[] {"cd /sdcard/music/ ; cp pic1 /sdcard/pic1"});
} catch (Exception ex){
String toast = null;
Log.i(toast, "Couldn't copy file", ex);
}
}
});
In this code you
1) go to the /sdcard/music
2) copy from /sdcard/music pic1 to /sdcard/pic1
I'm speculating, but you may have misunderstood what the parameter to exec really is. It's not a list of commands to be executed (effectivly a batch/shell script), but a single command WITH it's arguments to be executed by a shell. Making it a one-liner like Pepelac suggests or putting the series of commands into a single file that you execute with exec later may be what you are looking for. For the command you are trying to execute there is absolute no reason why you can not make it a one-liner with the full source path included (instead of changing to it), but there may be other reasons why you need to do this that you have not mentioned.
I am developing in J2ME, I need to show a text, and then an underlined link / button that people can press.
I cannot use Canvas.
As a temporal solution, I am using the typical command button but I would like to show this option on screen.
(I don't want to use any framework that implies to change everything so that it has a particular look, only an underlined link)
I found it, uff!!!
Command prospectoCommand = new Command("Prospecto", Command.EXIT, 1);
StringItem messageItem2 = new StringItem("", "", Item.HYPERLINK);
messageItem2.setText("push to go to the URL");
ItemCommandListener listener = new ItemCommandListener() {
public void commandAction(Command cmnd, Item item) {
if(cmnd==prospectoCommand)
{
try {
midlet.platformRequest(URL);
} catch (ConnectionNotFoundException ex) {
ex.printStackTrace();
}
}
}
};
messageItem2.setDefaultCommand(prospectoCommand);