So I can't seem to find an answer to get this to work the way i want, hoping someone here may know...
I have my gradle setup with different build variants and it works fine to switch between them or generate signed apk for the chosen variant. However what I'm looking to do (ideally in 1 click) is generate each variant's apk and name it accordingly with the version number and variant name.
Any ideas?
I've tried the following snippet
Code:
android {
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
def fileName = outputFile.name.replace('.apk', "-${versionName}.apk")
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
}
but no joke, if i went to modify it..it froze android studio. thanks!
Related
So I'm learning Java right now, starting off with simple programs. I need to make a program that displays "1-10" when the user inputs one of the numbers and ""11-20" if it's one of those. I have no idea what lines I'm missing, and I'm sure someone here can help me.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package coinflip2;
/**
*
* @author Class
*/
import java.util.Scanner;
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
System.out.print("Input a Number from 1-20: ");
int num = scan.nextInt();
while (num < 1 || num > 20)
{
System.out.print ("Not in range. Please enter a number from 1 to 20. ");
{
if (num >= 1 || num <=10)
System.out.print("1-10");
else
System.out.print("11-20");
}
}
}
}
Click to expand...
Click to collapse
im also really new to java im kinda self teaching. when u tried to compile what were ur error messages
Wait, I messed something up. before I posted it I was able to actually input a number. Let me take a look at it and I'll edit the first post.
Ok so I edited the first post.
I get no errors. It prompts me to input a number, and after I do it just says "Build Successful" and if I put in a number less than 1 or greater than 20 it prompts me to input a different number. So the first part I got right, I just need to get the print functions to work in the if/else statements.
EDIT!!! Ok I got it to work. This is now the final version if you want to know, even though it's very simple.
Just an update on what I have so far. Everything works but no matter what number between 1 and 20 I put I still get the same answer.
Also sorry for spamming like that, but I'm sure someone can actually learn from my mistakes .
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package coinflip2;
/**
*
* @author Class
*/
import java.util.Scanner;
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
System.out.print("Input a Number from 1-20: ");
int num = scan.nextInt();
while (num < 1 || num > 20)
{
System.out.print ("Not in range. Please enter a number from 1 to 20. ");
num = scan.nextInt();
}
{
if (num >= 1 && num <=10)
System.out.println("1-10");
else
System.out.println("11-20");
}
}
}
Click to expand...
Click to collapse
I am relatively new to programing and have been teaching myself as I go. I am trying to now integrate ESPN's API into my app which outputs XML data. I have done enough research to understand that I need to use an XML parser and that the XML can be displayed as a list view or web view by adding HTML markup.
I would like this thread to become a general discussion for all new developers on what XML parsing is and what it does. How it works, the code behind it etc.
I am currently trying to modify a code snippet from the developer.google.com website.
Android includes built in libraries for XML Parsing.
You can see a minimal use of the library here:
Code:
import java.io.IOException;
import java.io.StringReader;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
public class SimpleXmlPullApp
{
public static void main (String args[])
throws XmlPullParserException, IOException
{
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput( new StringReader ( "<foo>Hello World!</foo>" ) );
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if(eventType == XmlPullParser.START_DOCUMENT) {
System.out.println("Start document");
} else if(eventType == XmlPullParser.START_TAG) {
System.out.println("Start tag "+xpp.getName());
} else if(eventType == XmlPullParser.END_TAG) {
System.out.println("End tag "+xpp.getName());
} else if(eventType == XmlPullParser.TEXT) {
System.out.println("Text "+xpp.getText());
}
eventType = xpp.next();
}
System.out.println("End document");
}
}
So essentially, you can grab the xml from ESPN, save it to a file, parse it with that library, and output as desired.
Full details here: http://developer.android.com/reference/org/xmlpull/v1/XmlPullParser.html
the fastest way I know is the parser written in c/c++ and compiled with ndk.
bitpushr said:
Android includes built in libraries for XML Parsing.
So essentially, you can grab the xml from ESPN, save it to a file, parse it with that library, and output as desired.
Full details here: http://developer.android.com/reference/org/xmlpull/v1/XmlPullParser.html
Click to expand...
Click to collapse
I will have to try out this code. Because I am learning as I go there are many things in java I don't yet understand which ultimately make it a lot harder to accomplish tasks but I am slowly catching on
If you want to do this in a .NET (Windows x86/64, Windows Mobile, Windows Phone) environment, or a Linux MONO environment then the following will carry out the bare minimum of parsing.
Assuming you have the data in an XML file :- PARAMS.XML in the same folder as the program, created similar to this:
Code:
<?xml version="1.0" encoding="UTF-8" ?>
<PARAMS>
<Library>TESTLIB</Library>
<Source>C:\RetData\</Source>
</PARAMS>
Then the following C# code will read and extract the parameters:
Code:
using System.Xml;
string LibName,RetDir;
XmlReader xrdr = XmlReader.Create(Application.StartupPath+"\\PARAMS.xml");
xrdr.ReadToFollowing("Library");
Libname=xrdr.ReadElementContentAsString();
xrdr.ReadToFollowing("Source");
RetDir = xrdr.ReadElementContentAsString();
xrdr.Close();
After executing this code then:
LibName = "TESTLIB"
RetDir = "C:\RetData\"
CAVEAT:
I mentioned that this is the bare minimum. An XmlReader object is a forward only reader. Also, this code has no error checking.
In this case the elements must be read in the order they occur or the reader will encounter a null element and throw an error.
I have tried this :
Code:
buildTypes{
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = file("$project.buildDir/apk/test.apk")
}
}
But it doesn't work with version of gradle I have:
Error15, 0) Gradle DSL method not found: 'buildTypes()'
Possible causes:<ul><li>The project 'HexapodController' may be using a version of Gradle that does not contain the method.
Gradle settings</li><li>The build file may be missing a Gradle plugin.
Apply Gradle plugin</li>
According to document, trying to use MODE_WORLD_READABLE will crash the module UI with a SecurityException.
I've tried to use a ContentProvider, but unable to get the Context object in handleLoadPackage (Illegal state).
Is there any better way?
Tried to downgrade targetSdkVersion, the app no longer crashes but XSharedPreferences still can't read the file (the preferences file is already world readable)
You can use Remotepreferences (awesome library!). You will need a context however, so it is not suitable for methods in initzigote or where you can't access the context. I think is the only way as of now.
Massi-X said:
You can use Remotepreferences (awesome library!). You will need a context however, so it is not suitable for methods in initzigote or where you can't access the context. I think is the only way as of now.
Click to expand...
Click to collapse
Remotepreferences will complicate things.
The easiest way to do is to remove the below line
Code:
getPreferenceManager().setSharedPreferencesMode(MODE_WORLD_READABLE);
And add the following on class level.
Code:
@Override
public void onPause() {
super.onPause();
// Set preferences permissions to be world readable
// Workaround for Android N and above since MODE_WORLD_READABLE will cause security exception and FC.
final File dataDir = new File(getActivity().getApplicationInfo().dataDir);
final File prefsDir = new File(dataDir, "shared_prefs");
final File prefsFile = new File(prefsDir, getPreferenceManager().getSharedPreferencesName() + ".xml");
if (prefsFile.exists()) {
dataDir.setReadable(true, false);
dataDir.setExecutable(true, false);
prefsDir.setReadable(true, false);
prefsDir.setExecutable(true, false);
prefsFile.setReadable(true, false);
prefsFile.setExecutable(true, false);
}
}
This method will work on any sdk :good:
I tested it myself and it is working fine.
Thanks to @PunchUp @pyler
laura almeida said:
Remotepreferences will complicate things.
The easiest way to do is to remove the below line
Code:
getPreferenceManager().setSharedPreferencesMode(MODE_WORLD_READABLE);
And add the following on class level.
Code:
@Override
public void onPause() {
super.onPause();
// Set preferences permissions to be world readable
// Workaround for Android N and above since MODE_WORLD_READABLE will cause security exception and FC.
final File dataDir = new File(getActivity().getApplicationInfo().dataDir);
final File prefsDir = new File(dataDir, "shared_prefs");
final File prefsFile = new File(prefsDir, getPreferenceManager().getSharedPreferencesName() + ".xml");
if (prefsFile.exists()) {
dataDir.setReadable(true, false);
dataDir.setExecutable(true, false);
prefsDir.setReadable(true, false);
prefsDir.setExecutable(true, false);
prefsFile.setReadable(true, false);
prefsFile.setExecutable(true, false);
}
}
This method will work on any sdk :good:
I tested it myself and it is working fine.
Thanks to @PunchUp @pyler
Click to expand...
Click to collapse
Yeah but it seems an hacky thing. It will work with any Android? With selinux enabled? On custom ROMs? Surely Remotepreferences complicate things but is the best way (also for previous Android versions) of reading the preferences file. Anyway this can be another solution :good:
EDIT: I also found in marshmallow my apps was randomly failing reading the preferences (no real reason) and Remotepreferences solved the problem.
Massi-X said:
Remotepreferences will complicate things.
The easiest way to do is to remove the below line
And add the following on class level.
Yeah but it seems an hacky thing. It will work with any Android? With selinux enabled? On custom ROMs? Surely Remotepreferences complicate things but is the best way (also for previous Android versions) of reading the preferences file. Anyway this can be another solution :highfive:
Click to expand...
Click to collapse
With any android version - Yes
Will it work with previous android version - Yes
On custom ROMs - Yes
With selinux enabled ? - not tested yet. But I think it works.
laura almeida said:
With any android version - Yes
Will it work with previous android version - Yes
On custom ROMs - Yes
With selinux enabled ? - not tested yet. But I think it works.
Click to expand...
Click to collapse
Previous versions: I was speaking about another thing. See edit. Anyway it's another way, 2 is always better than 1.
Library: DexKit
Project Link: https://github.com/LuckyPray/DexKit
About: An easy-to-use, high-performance dex deobfuscation library. Easy to use your CMAKE/Android projects.
Highlight:
JNI multi-threaded processing Dex bytecode, more efficient than JVM implementation.
It single search is ms level, You can even inject the host application at runtime without causing an ANR, to the extent permitted.
You can use it to handle reinforced apps(use ClassLoader cookies).
API introductionThere are two APIs can meet most of your usage scenarios:
DexKit::BatchFindClassesUsingStrings
DexKit::BatchFindMethodsUsingStrings
Note: In all cases you should avoid searching for keywords that contain duplicate content, eg: {"key_word", "word"}, as this will cause tags to be overwritten, resulting in inaccurate search results. If there is such a need, open the advanced search mode as much as possible, and use the string to match the content exactly, for example, modify it to this: {"^key_word$", "^word$"}
Click to expand...
Click to collapse
And there are many other APIs:
DexKit::FindMethodCaller: find caller for specified method.
DexKit::FindMethodInvoking: find the called method
DexKit::FindMethodUsingField: Find method to get/set specified field
DexKit::FindMethodUsingString: find method used utf8 string
DexKit::FindMethod: find method by multiple conditions
DexKit::FindSubClasses: find all direct subclasses of the specified class
DexKit::FindMethodUsingOpPrefixSeq: find all method using opcode prefix sequence(op range: 0x00-0xFF)
DexKit::FindMethodUsingOpCodeSeq: find all method using opcode sequence(op range: 0x00-0xFF)
DexKit::GetMethodOpCodeSeq: get method opcode sequence(op range: 0x00-0xFF)
Note: At present, all instructions are only for standard dex instructions and do not include odex optimization instructions.
Click to expand...
Click to collapse
For more detailed instructions, please refer to dex_kit.h.
Quick startHowever, this approach will import an extra so file. If you don't want to import an extra so file, please use the second/third method.
build.gradle:
Code:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
app/build.gradle:
Code:
dependencies {
implementation 'com.github.LuckyPray:DexKit:<version>'
}
JAVA ExampleDexKitBridge provides 2 factory methods to create Dexkit instances:
DexKitBridge.create(apkPath): normally, please use it.
DexKitBridge.create(classLoader, true): for reinforced apps, used classLoader and set option useCookieDexFile to true.
PS: DexKitBridge.create(classLoader, useCookieDexFile = false) ≈ DexKitBridge.create(apkPath), but the former may contain part of the system dex.
Java:
import io.luckypry.dexkit.DexKitBridge;
// ...
public class DexUtil {
static {
System.loadLibrary("dexkit");
}
public static void findMethod() {
// for no-reinforced apps please use apkpath to load, because of the exist of dex2oat and CompactDex(cdex),
// dexkit currently only handles StandardDex.
String apkPath = application.applicationInfo.sourceDir
// try-with-resources, auto close DexKitBridge, no need to call DexKitBridge.close()
// if you don't use try-with-resources, be sure to manually call DexKitBridge.close() to release the jni memory
try (DexKitBridge dexKitBridge = DexKitBridge.create(apkPath)) {
if (dexKitBridge == null) {
Log.e("DexUtil", "DexKitBridge create failed");
return;
}
List<DexClassDescriptor> classes = dexKitBridge.findSubClasses("android.app.Activity", null);
for (DexClassDescriptor clazz : classes) {
String name = clazz.getName();
String simpleName = clazz.getSimpleName();
Class<?> clz = clazz.getClassInstance(hostClassLoader);
Log.i("DexUtil", "findSubClasses: " + clz);
}
} catch (Throwable e) {
Log.e("DexUtil", Log.getStackTraceString(e));
}
}
}
If you have problems using it, please create an issue on the github repo.
Reserved