Chimpchat automatic journey - android

My goal is to make a monkey visit all pages/activity of a given android application.
I am currently using Chimpchat and my first steps are as following :
1 - Connection to the device :
TreeMap<String, String> options = new TreeMap<String, String>();
options.put("backend", "adb");
options.put("adbLocation", ADB);
mChimpchat = ChimpChat.getInstance(options);
mDevice = mChimpchat.waitForConnection(TIMEOUT, ".*");
mDevice.wake();
2 - Getting a list of view IDs :
mDevice.getViewIdList();
3 - For each strings (using iterator it) ID contains in list returned by getViewIdList(), I would like to access Class, Text if any, bounds, etc ...
while (it.hasNext()) {
String s = it.next();
System.out.println(s + " : ");
try {
IChimpView v = mDevice.getView(By.id(s));
System.out.println(v);
System.out.println(v.getViewClass() + " : " );
if (v.getViewClass().toString() == "TextView") {
System.out.print(v.getText());
}
} catch (Exception e) {
e.printStackTrace();
}
}
I get an exception on the
v.getViewClass()
com.android.chimpchat.core.ChimpException: Node with given ID does not exist
at com.android.chimpchat.ChimpManager.queryView(ChimpManager.java:415)
at com.android.chimpchat.core.ChimpView.queryView(ChimpView.java:53)
at com.android.chimpchat.core.ChimpView.getViewClass(ChimpView.java:96)
at JavaMonkey.listViewsID(JavaMonkey.java:80)
at JavaMonkey.main(JavaMonkey.java:114)
If anyone can point my mistake(s) or point me to another approach, it would be greatly appreciated !

I think Robotium would be much better suited for this type of testing. Accessing views on a remote device using adb/MonkeyRunner is not very reliable in my experience. In addition, Robotium has a bunch of cool features and can be easily integrated into an existing test suite.

I think that the issue is that there is no Activity running.
As I commented above you might be able to use startActivity to start one.
However that will take some digging to figure out what all needs to be passed in.
Another solution is as follows:
StringBuilder builder = new StringBuilder();
builder.append("am start -a android.intent.action.MAIN -n ");
builder.append(mPackage).append("/").append(mActivity);
String output = mDevice.shell(builder.toString());
This will use the adb shell to launch the application.
mPackage = the package path (com.company.application) and mActivity = the activity (.MyActivity). From there you should be able to mDevice.getHierarchyViewer() or mDevice.getViewIdList()

Related

Low Rhino performance on android real device

I'm having low Rhino performance issues while executing Rhino code on Android real device.
The Rhino context is initiated with a string which represents big JSON object, the total string size is around 120K, to test code performance we wrote a few instrumental tests to check the code performance, however, we are getting not clear result the same code, with the same parameters shows absolutely different results between tests and sample app.
The test performance 10 times faster than the same code is executed as an instrumental test then on it's running as part of the sample app on the same device (G5). BTW the android emulator also shows good performance result.
the code is pretty simple
private void init(String jFfunctionsDeclaration) throws ScriptInitException {
StringBuilder ruleEngineContextBuffer = new StringBuilder();
//create a JSON object in the string representation, later Rhino context will be initialized with this string
for (Map.Entry<String, String> e : scriptObjects.entrySet()) {
String key = e.getKey();
String value = e.getValue();
ruleEngineContextBuffer.append("\nvar ");
ruleEngineContextBuffer.append(key);
ruleEngineContextBuffer.append(" = "); // append(" = JSON.parse(");
ruleEngineContextBuffer.append(value);
}
// create and enter safe execution context to prevent endless loop or deadlock in JS
// because Rhino input it provided from outside
SafeContextFactory safeContextFactory = new SafeContextFactory();
rhino = safeContextFactory.makeContext().enter();
try {
// the fisrt init step, init Rhino cotext with JS utils methods
// functions input is the list of JS functions
sharedScope = rhino.initStandardObjects();
rhino.evaluateString(sharedScope, functions, "<init1>", 1, null);
String str = ruleEngineContextBuffer.toString();
long startContextInit = System.currentTimeMillis();
rhino.evaluateString(sharedScope, str, "<init2>", 1, null);
long totalContextInit = System.currentTimeMillis() - startContextInit;
Log.d(TAG, "Rhino context init duration = " + totalContextInit);
} catch (Throwable e) {
throw new ScriptInitException("Javascript shared scope initialization error: " + e.getMessage());
}
}
could someone explain me this mystery, thanks.

How to share split APKs created while using instant-run, within Android itself?

Background
I have an app (here) that, among other features, allows to share APK files.
In order to do so, it reaches the file by accessing the path of packageInfo.applicationInfo.sourceDir (docs link here), and just shares the file (using ContentProvider when needed, as I've used here).
The problem
This works fine in most cases, especially when installing APK files from either the Play Store or from a standalone APK file, but when I install an app using Android-Studio itself, I see multiple APK files on this path, and none of them are valid ones that can be installed and run without any issues.
Here's a screenshot of the content of this folder, after trying out a sample from "Alerter" github repo :
I'm not sure when this issue has started, but it does occur at least on my Nexus 5x with Android 7.1.2. Maybe even before.
What I've found
This seems to be caused only from the fact that instant run is enabled on the IDE, so that it could help updating the app without the need to re-build it all together :
After disabling it, I can see that there is a single APK, just as it used to be in the past:
You can see the difference in file size between the correct APK and the split one.
Also, it seems that there is an API to get the paths to all of the splited APKs:
https://developer.android.com/reference/android/content/pm/ApplicationInfo.html#splitPublicSourceDirs
The question
What should be the easiest way to share an APK that got to be split into multiple ones ?
Is it really needed to somehow merge them?
It seems it is possible according to the docs :
Full paths to zero or more split APKs that, when combined with the
base APK defined in sourceDir, form a complete application.
But what's the correct way to do it, and is there a fast and efficient way to do it? Maybe without really creating a file?
Is there maybe an API to get a merged APK out of all the split ones? Or maybe such an APK already exist anyway in some other path, and there is no need for merging?
EDIT: just noticed that all third party apps that I've tried are supposed to share an installed app's APK fail to do so in this case.
I am the tech lead #Google for the Android Gradle Plugin, let me try to answer your question assuming I understand your use case.
First, some users mentioned you should not share your InstantRun enabled build and they are correct. The Instant Run builds on an application is highly customized for the current device/emulator image you are deploying to. So basically, say you generate an IR enabled build of your app for a particular device running 21, it will fail miserably if you try to use those exact same APKs on say a device running 23. I can go into much deeper explanation if necessary but suffice to say that we generate byte codes customized on the APIs found in android.jar (which is of course version specific).
So I do not think that sharing those APKs make sense, you should either use a IR disabled build or a release build.
Now for some details, each slice APK contains 1+ dex file(s), so in theory, nothing prevents you from unziping all those slice APKs, take all the dex files and stuff them back into the base.apk/rezip/resign and it should just work. However, it will still be an IR enabled application so it will start the small server to listen to IDE requests, etc, etc... I cannot imagine a good reason for doing this.
Hope this helps.
To merge multiple split apks to an single apk might be a little complicated.
Here is a suggestion to share the split apks directly and let the system to handle the merge and installation.
This might not be an answer to the question, since it's a little long, I post here as an 'answer'.
Framework new API PackageInstaller can handle monolithic apk or split apk.
In development environment
for monolithic apk, using adb install single_apk
for split apk, using adb install-multiple a_list_of_apks
You can see these two modes above from android studio Run output depends on your project has Instant run enable or disable.
For the command adb install-multiple, we can see the source code here, it will call the function install_multiple_app.
And then perform the following procedures
pm install-create # create a install session
pm install-write # write a list of apk to session
pm install-commit # perform the merge and install
What the pm actually do is call the framework api PackageInstaller, we can see the source code here
runInstallCreate
runInstallWrite
runInstallCommit
It's not mysterious at all, I just copied some methods or function here.
The following script can be invoked from adb shell environment to install all split apks to device, like adb install-multiple. I think it might work programmatically with Runtime.exec if your device is rooted.
#!/system/bin/sh
# get the total size in byte
total=0
for apk in *.apk
do
o=( $(ls -l $apk) )
let total=$total+${o[3]}
done
echo "pm install-create total size $total"
create=$(pm install-create -S $total)
sid=$(echo $create |grep -E -o '[0-9]+')
echo "pm install-create session id $sid"
for apk in *.apk
do
_ls_out=( $(ls -l $apk) )
echo "write $apk to $sid"
cat $apk | pm install-write -S ${_ls_out[3]} $sid $apk -
done
pm install-commit $sid
I my example, the split apks include (I got the list from android studio Run output)
app/build/output/app-debug.apk
app/build/intermediates/split-apk/debug/dependencies.apk
and all apks under app/build/intermediates/split-apk/debug/slices/slice[0-9].apk
Using adb push all the apks and the script above to a public writable directory, e.g /data/local/tmp/slices, and run the install script, it will install to your device just like adb install-multiple.
The code below is just another variant of the script above, if your app has platform signature or device is rooted, I think it will be ok. I didn't have the environment to test.
private static void installMultipleCmd() {
File[] apks = new File("/data/local/tmp/slices/slices").listFiles(new FileFilter() {
#Override
public boolean accept(File pathname) {
return pathname.getAbsolutePath().endsWith(".apk");
}
});
long total = 0;
for (File apk : apks) {
total += apk.length();
}
Log.d(TAG, "installMultipleCmd: total apk size " + total);
long sessionID = 0;
try {
Process pmInstallCreateProcess = Runtime.getRuntime().exec("/system/bin/sh\n");
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(pmInstallCreateProcess.getOutputStream()));
writer.write("pm install-create\n");
writer.flush();
writer.close();
int ret = pmInstallCreateProcess.waitFor();
Log.d(TAG, "installMultipleCmd: pm install-create return " + ret);
BufferedReader pmCreateReader = new BufferedReader(new InputStreamReader(pmInstallCreateProcess.getInputStream()));
String l;
Pattern sessionIDPattern = Pattern.compile(".*(\\[\\d+\\])");
while ((l = pmCreateReader.readLine()) != null) {
Matcher matcher = sessionIDPattern.matcher(l);
if (matcher.matches()) {
sessionID = Long.parseLong(matcher.group(1));
}
}
Log.d(TAG, "installMultipleCmd: pm install-create sessionID " + sessionID);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
StringBuilder pmInstallWriteBuilder = new StringBuilder();
for (File apk : apks) {
pmInstallWriteBuilder.append("cat " + apk.getAbsolutePath() + " | " +
"pm install-write -S " + apk.length() + " " + sessionID + " " + apk.getName() + " -");
pmInstallWriteBuilder.append("\n");
}
Log.d(TAG, "installMultipleCmd: will perform pm install write \n" + pmInstallWriteBuilder.toString());
try {
Process pmInstallWriteProcess = Runtime.getRuntime().exec("/system/bin/sh\n");
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(pmInstallWriteProcess.getOutputStream()));
// writer.write("pm\n");
writer.write(pmInstallWriteBuilder.toString());
writer.flush();
writer.close();
int ret = pmInstallWriteProcess.waitFor();
Log.d(TAG, "installMultipleCmd: pm install-write return " + ret);
checkShouldShowError(ret, pmInstallWriteProcess);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
try {
Process pmInstallCommitProcess = Runtime.getRuntime().exec("/system/bin/sh\n");
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(pmInstallCommitProcess.getOutputStream()));
writer.write("pm install-commit " + sessionID);
writer.flush();
writer.close();
int ret = pmInstallCommitProcess.waitFor();
Log.d(TAG, "installMultipleCmd: pm install-commit return " + ret);
checkShouldShowError(ret, pmInstallCommitProcess);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
private static void checkShouldShowError(int ret, Process process) {
if (process != null && ret != 0) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String l;
while ((l = reader.readLine()) != null) {
Log.d(TAG, "checkShouldShowError: " + l);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Meanwhile, the simple way, you can try the framework api. Like the sample code above, it might work if the device is rooted or your app has platform signature, but I didn't get a workable environment to test it.
private static void installMultiple(Context context) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams sessionParams = new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);
try {
final int sessionId = packageInstaller.createSession(sessionParams);
Log.d(TAG, "installMultiple: sessionId " + sessionId);
PackageInstaller.Session session = packageInstaller.openSession(sessionId);
File[] apks = new File("/data/local/tmp/slices/slices").listFiles(new FileFilter() {
#Override
public boolean accept(File pathname) {
return pathname.getAbsolutePath().endsWith(".apk");
}
});
for (File apk : apks) {
InputStream inputStream = new FileInputStream(apk);
OutputStream outputStream = session.openWrite(apk.getName(), 0, apk.length());
byte[] buffer = new byte[65536];
int count;
while ((count = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, count);
}
session.fsync(outputStream);
outputStream.close();
inputStream.close();
Log.d(TAG, "installMultiple: write file to session " + sessionId + " " + apk.length());
}
try {
IIntentSender target = new IIntentSender.Stub() {
#Override
public int send(int i, Intent intent, String s, IIntentReceiver iIntentReceiver, String s1) throws RemoteException {
int status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE);
Log.d(TAG, "send: status " + status);
return 0;
}
};
session.commit(IntentSender.class.getConstructor(IIntentSender.class).newInstance(target));
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
session.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
In order to use the hidden api IIntentSender, I add the jar library android-hidden-api as the provided dependency.
Those are called split apks. Which is mainly used in the PlayStore. As you may know, PlayStore only shows apps to the user if it's compatible with the device. Same in this case. The split has files varies from devices. Like if you used Different resources for Different devices which makes app really heavy. By making splits, it saves space for downloading and running for the user by only downloading the usable split apks.
Is it possible to merge them into single apk?
Yes. I used an app called Anti Split which allows that. Plus Apk Editor Ultra has same.
Can we save it into a single file?
Yes you can. As like for Anti Split, you have to first backup the app. Like in this case you have to back it up as apks file or xapk which is called bundled app in Android Studio. I have created a library for doing this. It's working perfectly for me. Am using it to backup apps into xapk which can later be installed using SIA app or XAPK Installer or we can use xapk file to merge it and make apk
For me instant run was a nightmare, 2-5 minute build times, and maddeningly often, recent changes were not included in builds. I highly recommend disabling instant run and adding this line to gradle.properties:
android.enableBuildCache=true
First build often takes some time for large projects (1-2mins), but after it's cached subsequent builds are usually lightnight fast (<10secs).
Got this tip from reddit user /u/QuestionsEverythang which has saved me SO much hassling around with instant run!

How to change DNS in android 4.x+ using internal linux commands within app?

I have been working on this small project in college about changing the default DNS of wifi network to a custom DNS like Google, OpenDNS, Metacert, etc.
I know I have to write a shellscript inside the app's code that would edit the hosts file in the filesystem.
The problem is I have no idea where to start from. I have researched on google for some time and I couldn't figure anything.
If anyone knows about it, please guide me. Please tell me the name of the file to be edited, its location, what commands are required and how to run those commands' combination as a shellscript on a click of a button on the UI of app.
EDIT : I'm stuck only at this. Any help will be greatly appreciated.
I'm not sure about which files you would have to edit but this should give you the tools you need to do that.
The first thing you need to do is root the phone if you haven't already. If it's not rooted, you'll run into an issue like: Working Directory : null environment when running Process.Builder on android
There are a lot of guides available for that online. Install SuperSU as well. In order to run shell commands or scripts you should look at the ProcessBuilder class in Android:
http://developer.android.com/reference/java/lang/ProcessBuilder.html
I've given some sample code below to help you along the way. You could execute this in an OnClick() for a button.
/**
* Runs the shell command.
*
* #param command an array of Strings. command[0] contains the name of the
* shell command. command[1]... contains parameters.
*
* #return the text outputted by the command to stderr or stdout
*/
String runCmd(String[] command, boolean readOutput,
boolean waitForExit) {
ProcessBuilder probuilder = new ProcessBuilder()
.command(command)
.redirectErrorStream(true);
String output = "";
Process process;
// Log.d("MyShellCommand", "Executing " + command[0]);
try {
process = probuilder.start();
} catch(IOException e) {
return e.getMessage();
}
if (readOutput) {
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
try {
while ((line = br.readLine()) != null) {
// Log.d("MyShellCommand", "Read a line: " + line);
output += line + "\n";
}
} catch(IOException e) {
output = e.getMessage();
}
}

ERROR_WRONG_LABEL when trying to print wireless using Android Brother Sdk for label printer

I have trying to print using labels from my android app which using wifi commands Brother QL-720NW label printer. Since I performed factory reset on the printer , I'm getting this error
Problem: ERROR_WRONG_LABEL( means wrong roll specified in the sdk guide) error is thrown on print command, since I performed factory
reset on the printer .
CODE:
void printTemplateSample()
{
Printer myPrinter = new Printer();
PrinterInfo myPrinterInfo = new PrinterInfo();
try{
// Retrieve printer informations
myPrinterInfo = myPrinter.getPrinterInfo();
// Set printer informations
myPrinterInfo.printerModel = PrinterInfo.Model.QL_720NW;
myPrinterInfo.port=PrinterInfo.Port.NET;
myPrinterInfo.printMode=PrinterInfo.PrintMode.FIT_TO_PAGE;
// :
myPrinterInfo.paperSize = PrinterInfo.PaperSize.A4;
myPrinterInfo.ipAddress="192.168.1.13";
myPrinterInfo.macAddress="00:80:92:BD:35:7D";
myPrinter.setPrinterInfo(myPrinterInfo);
// Start creating P-touch Template command print data
// myPrinter.startPTTPrint(1, null);
Boolean val= myPrinter.startPTTPrint(6, null);
Log.i("print", "startPTTPrint "+val);
// Replace text
myPrinter.replaceText("abcde");
// myPrinter.replaceText("12345");
// Trasmit P-touch Template command print data
PrinterStatus status=myPrinter.flushPTTPrint();//ERROR thrown here
Log.i("print", "PrinterStatus err"+status.errorCode);
}catch(Exception e){
e.printStackTrace();
}
}
I'm using there sample code from here
Objective - my ultimate objective is to replace text in template and print but currently I'm not able to print anything
I'm using this Brother SDK.
I tried the Brother sample code for android , it also gives the same error
BUT brother i print app and Ptouch software are successfully printing without any error.
Please help!
Thanks
I resolved this by creating a LabelInfo object, since you have a Label Printer. It's not clear at all in the documentation. You need to set the label info after the printer info.
PrinterInfo info = myPrinter.getPrinterInfo();
info.paperSize = PrinterInfo.PaperSize.CUSTOM;
LabelInfo mLabelInfo = new LabelInfo();
mLabelInfo.labelNameIndex = 5;
mLabelInfo.isAutoCut = true;
mLabelInfo.isEndCut = true;
mLabelInfo.isHalfCut = false;
mLabelInfo.isSpecialTape = false;
myPrinter.setPrinterInfo(info);
myPrinter.setLabelInfo(mLabelInfo);
The ERROR_WRONG_LABEL means that you have a wrong value in paperSize or labelNameIndex.
I have a P750W label printer with a 24'' paper. I found that value 5 is the good one for this size, but I don't know for your printer.
I had the same problem and figured out that you should specify the labelNameIndex field to the PrinterInfo object.
I had the QL-810W printer. I tried many values and nothing worked until I set it to:
printerInfo.labelNameIndex = LabelInfo.QL700.W62RB.ordinal // -> 17
I figured out the correct value by making a for loop with all integers from 0 to 100 and logging the result until the printing succeeded with this value. I know this is not the optimal solution but I can't find any documentation or reference for these codes.
Here is the code I used to specify the PrinterInfo object:
val printerInfo = PrinterInfo()
printerInfo.printerModel = PrinterInfo.Model.QL_810W
printerInfo.port = PrinterInfo.Port.NET
printerInfo.orientation = PrinterInfo.Orientation.PORTRAIT
printerInfo.paperSize = PrinterInfo.PaperSize.CUSTOM
printerInfo.align = PrinterInfo.Align.CENTER
printerInfo.valign = PrinterInfo.VAlign.MIDDLE
printerInfo.printMode = PrinterInfo.PrintMode.ORIGINAL
printerInfo.numberOfCopies = 1
printerInfo.labelNameIndex = LabelInfo.QL700.W62RB.ordinal // -> 17
printerInfo.isAutoCut = true
printerInfo.isCutAtEnd = false
return printerInfo
TL;DR
I solved by setting the workPath attribute:
printerInfo.workPath = context.cacheDir.Path
I noticed that the setPrinterInfo was returning false and when trying to print I received the WRONG_LABEL error code. Debugging the code I figured out that it's related to file writing permission that Brother SDK requires. The documentation is confusing and mentions about needing the WRITE_EXTERNAL_STORAGE if workPath isn't set. Even having this permission I could not make it work. I solved by setting the workPath attribute as shown above.

Encoding issues using ADB to dispatch messages

I've implemented a service that listens to commands issued through ADB. An example of a command sent through ADB could look like this:
adb shell am startservice -a com.testandroid.SEND_SMS -e number 123123123 -e message "åäö"
Now, the problem here is that the encoding of the string "åäö" seems to mess up. If I take that string extras and immediately output it to the log, I get a square "[]", unknown character. If I send this message I get chinese characters in the messages app. As long as I stick to non-umlaut characters (ASCII I guess), everything works fine.
I'm using Windows 7 and the command line for this. I have not touched the encoding of the command line and I've tried to process the extras string by getting the byte characters, passing in UTF-8 as an encoding argument, then creating a new String passing in UTF-8 as an encoding argument there as well. No dice, though.
The values of the bytes, when using getBytes() are å: -27, ä: -92, ö: -74
How do I get this to play nice so I can make use of at least the umlauts?
All of this works perfectly fine in Linux.
i ran into the same issue, but finally i got it work!
if you use for example C#, you have to do it like the following example:
02.12.2019
According to the protocol.txt, the ADB-Protocol supports "smart-sockets". Those sockets can be used to do all the stuff, the ADB-Client inside the adb.exe does. For example if you want upload an file, you have to request such an "smart-socket". After that, you have to follow the protocol assigned to the service (for an service overview see SERVICE.txt) as described, for example, in the SYNC.txt.
13.10.2014
public static List<string> ExecuteBG(string exe, string args, int timeOut = -1)
{
if (File.Exists(exe) || exe == "cmd.exe")
{
ProcessStartInfo StartInfo = new ProcessStartInfo();
StartInfo.FileName = exe;
StartInfo.Arguments = Encoding.Default.GetString(Encoding.UTF8.GetBytes(args));
StartInfo.CreateNoWindow = true;
StartInfo.UseShellExecute = false;
StartInfo.RedirectStandardError = true;
StartInfo.RedirectStandardOutput = true;
StartInfo.StandardErrorEncoding = Encoding.UTF8;
StartInfo.StandardOutputEncoding = Encoding.UTF8;
AutoResetEvent errorWaitHandle = new AutoResetEvent(false);
AutoResetEvent outputWaitHandle = new AutoResetEvent(false);
List<string> response = new List<string>();
Process proc = new Process();
proc.StartInfo = StartInfo;
proc.ErrorDataReceived += (s, e) =>
{
if (String.IsNullOrEmpty(e.Data))
{
errorWaitHandle.Set();
}
else
{
response.Add(e.Data);
}
};
proc.OutputDataReceived += (s, e) =>
{
if (String.IsNullOrEmpty(e.Data))
{
outputWaitHandle.Set();
}
else
{
response.Add(e.Data);
}
};
proc.Start();
proc.BeginErrorReadLine();
proc.BeginOutputReadLine();
proc.WaitForExit(timeOut);
errorWaitHandle.WaitOne(timeOut);
outputWaitHandle.WaitOne(timeOut);
return response;
}
return new List<string>();
}
Really important is this part "StartInfo.Arguments = Encoding.Default.GetString(Encoding.UTF8.GetBytes(args));", here we convert the UTF8 string into the Windows "default" charset which is known by cmd. So we send a "destroyed" "default" encoded string to cmd and the Android shell will convert it back to UTF8. So we have the "umlauts" like "üöäÜÖÄàè etc.".
Hope this helps someone.
PS: If u need a working "Framework" which supports UTF8 push/pull for files/folders also have a look at my AndroidCtrl.dll it's C# .NET4 written.
Regards,
Sebastian
Concluding, either the problem is situated in cmd.exe or adb.exe. Until either one or both are updated to be more compliant with eachother I will sadly not be able to make use of this for the time being.

Categories

Resources