Appium run non shell ADB command - appium

This doc shows instructions how to run adb shell commands on Appium clients.
https://appium.io/docs/en/writing-running-appium/android/android-shell/
Map<String, Object> args = new HashMap<>();
args.put("command", "echo");
args.put("args", Lists.newArrayList("arg1", "arg2"));
String output = driver.executeScript("mobile: shell", args);
assert output.equals("arg1 arg2");
I want to run the adb push command:
Map<String, Object> args = new HashMap<>();
args.put("command", "push");
args.put("args", Lists.newArrayList("./app/images.zip", "/sdcard/Android/data/com.example.demoapp/files/images.zip"));
String output = driver.executeScript("mobile: shell", args);
assert output.equals("arg1 arg2");
However, the adb push command is not supported in the shell environment.
Any help?
I know something should change on the driver.executeScript("mobile: shell", args); Don't know what.

Can't you use the Appium Push File functionality?
driver.pushFile("./app/images.zip", new File("/sdcard/Android/data/com.example.demoapp/files/images.zip"));

Related

Why QProcess is not showing stdout from bash script executed in remote server?

I made an script (findx.h) that doesn't have any problem when i ran it on Solaris server via console (bash-3.2$ ./findx.sh)
The problem appears when i try to run it from a windows Qt app using QProcess (code below) where it doesn't display the ouput of the command.
I tried little variations and appear to show data when just use one pipe instead of two. But i need the two: grep and ggrep.
//findx.h in solaris
//WHAT WORKS
#!/bin/bash
echo pass | sudo -S /usr/sbin/snoop -x0 -ta HSM1000 port 1000
//WHAT I WANT
#!/bin/bash
echo pass | sudo -S /usr/sbin/snoop -x0 -ta HSM1000 port 1000 | /usr/sfw/bin/ggrep -A 2 KR01
//Qt on windows
QString commands="(";
commands +="source setpath.sh";
commands +=";/path/to/script/findx.sh";
commands +=")";
this->logged=false;
QString program = "plink.exe";
QStringList arguments;
arguments <<"-ssh"
<<ip
<<"-l"
<<user
<<"-pw"
<<pass
<<commands;
this->myProcess=new QProcess(this);
connect(this->myProcess,SIGNAL(started()),
this, SLOT(onprocess_started()));
connect(this->myProcess, SIGNAL(errorOccurred(QProcess::ProcessError)),
this, SLOT(onprocess_errorOcurred(QProcess::ProcessError)));
connect(this->myProcess, SIGNAL(finished(int, QProcess::ExitStatus)),
this, SLOT(onprocess_finished(int, QProcess::ExitStatus)));
connect(this->myProcess, SIGNAL(readyReadStandardError()),
this, SLOT(onprocess_readyReadStandardError()));
connect(this->myProcess, SIGNAL(readyReadStandardOutput()),
this, SLOT(onprocess_readyReadStandardOutput()));
connect(this->myProcess, SIGNAL(stateChanged(QProcess::ProcessState)),
this, SLOT(onprocess_stateChanged(QProcess::ProcessState)));
this->myProcess->start(program, arguments);
this->ui->labStatus->setText("Starting");
return 0;
// How i read, i do the same for stderr and put it also in plainOutput
QByteArray err=this->myProcess->readAllStandardOutput();
QString m="Standard output:"+QString(err.data());
this->ui->plainOutput->appendPlainText(m);
please any advice would be useful.
Thanks in advance.

Connecting to CosmosDB from Docker container

I am trying to learn Docker and am building up a solution slowly as I go. I created an Azure Function App that has one Http endpoint exposed. I created the Docker file to build and run the solution in a linux container(image:mcr.microsoft.com/azure-functions/dotnet:3.0, Debian image). I'm on a Windows machine.
I installed the Azure CosmosDB Emulator on my Windows machine and wanted to connect to it from the function app running in the linux container.
I am passing in the connection string for cosmos as an environment variable.
ARG COSMOS_CONNECTION_STRING="AccountEndpoint=https://host.docker.internal:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
I'm trying to connect to the emulator through the following code:
await new CosmosClient(Environment.GetEnvironmentVariable("AzureCosmosConnectionString", EnvironmentVariableTarget.Process)
.GetContainer("db_name", "container_name")
.UpsertItemAsync<Dto>(dto)
.ConfigureAwait(false);
When I do this, I'm getting the following error(I assume the first few lines are the most relevant, but am including the rest in case I'm wrong):
---> System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
at System.Net.Security.SslStream.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception)
at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
at System.Net.Security.SslStream.ThrowIfExceptional()
at System.Net.Security.SslStream.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
at System.Net.Security.SslStream.EndProcessAuthentication(IAsyncResult result)
at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__65_1(IAsyncResult iar)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean allowHttp2, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at Microsoft.Azure.Cosmos.DocumentClient.HttpRequestMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
at Microsoft.Azure.Cosmos.GatewayAccountReader.GetDatabaseAccountAsync(Uri serviceEndpoint)
at Microsoft.Azure.Cosmos.Routing.GlobalEndpointManager.GetDatabaseAccountFromAnyLocationsAsync(Uri defaultEndpoint, IList`1 locations, Func`2 getDatabaseAccountFn)
at Microsoft.Azure.Cosmos.GatewayAccountReader.InitializeReaderAsync()
at Microsoft.Azure.Cosmos.CosmosAccountServiceConfiguration.InitializeAsync()
at Microsoft.Azure.Cosmos.DocumentClient.InitializeGatewayConfigurationReaderAsync()
at Microsoft.Azure.Cosmos.DocumentClient.GetInitializationTaskAsync(IStoreClientFactory storeClientFactory)
at Microsoft.Azure.Cosmos.DocumentClient.EnsureValidClientAsync()
at Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler.EnsureValidClientAsync(RequestMessage request)
at Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler.SendAsync(RequestMessage request, CancellationToken cancellationToken)
at Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler.SendAsync(Uri resourceUri, ResourceType resourceType, OperationType operationType, RequestOptions requestOptions, ContainerInternal cosmosContainerble`1 partitionKey, Stream streamPayload, Action`1 requestEnricher, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken)
at Microsoft.Azure.Cosmos.ContainerCore.ProcessItemStreamAsync(Nullable`1 partitionKey, String itemId, Stream streamPayload, OperationType operationType, ItemRequestOptions requestOptions, CosmosDiagnostiiagnosticsContext, CancellationToken cancellationToken)
at Microsoft.Azure.Cosmos.ContainerCore.ExtractPartitionKeyAndProcessItemStreamAsync[T](Nullable`1 partitionKey, String itemId, T item, OperationType operationType, ItemRequestOptions requestOptions, CosmcsContext diagnosticsContext, CancellationToken cancellationToken)
at Microsoft.Azure.Cosmos.ContainerCore.UpsertItemAsync[T](T item, Nullable`1 partitionKey, ItemRequestOptions requestOptions, CancellationToken cancellationToken)
When I look at the emulator locally in my browser, it is using a localhost certificate(I assume one created with the dotnet cli).
Attempt 1
Export the localhost cert as a .pfx file and then get the linux container to trust that through the following commands(in my Dockerfile)
ARG CERTIFICATE_PASSWORD="Test|234"
RUN openssl pkcs12 \
-in "/src/localhost.pfx" \
-clcerts \
-nokeys \
-out "/src/localhost.crt" \
-passin pass:${CERTIFICATE_PASSWORD}
RUN cp "/src/localhost.crt" "/usr/local/share/ca-certificates/"
RUN update-ca-certificates
I assume this attempt doesn't work, at least in part, due to the fact that the certificate on the Windows machine is created for localhost, whereas to connect to it from docker, the address needs to be host.docker.internal.
Attempt 2
Add the exported certificate to the Kestrel process running the function app in hopes that it would then honor it by adding the following to my dockerfile
ENV ASPNETCORE_Kestrel__Certificates__Default__Path=/src/localhost.pfx
Attempt 3
Update the CosmosClient instantiation to include options overriding the HttpClientFactory as follows:
CosmosClient = new CosmosClient(
Environment.GetEnvironmentVariable("AzureCosmosConnectionString", EnvironmentVariableTarget.Process),
new CosmosClientOptions
{
HttpClientFactory = () =>
{
using (var httpClientHandler = new HttpClientHandler())
{
httpClientHandler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
return new HttpClient(httpClientHandler);
}
}
});
With every attempt above, I'm still seeing the same error. Not sure what else to try to get this to work...
Just found this issue on GitHub. Seems as though I'm not alone.
Update (2/10/2021)
The SDK now allows overriding SSL validation in an easy fashion (reference https://learn.microsoft.com/azure/cosmos-db/local-emulator?tabs=cli%2Cssl-netstd21#disable-ssl-validation):
CosmosClientOptions cosmosClientOptions = new CosmosClientOptions()
{
HttpClientFactory = () =>
{
HttpMessageHandler httpMessageHandler = new HttpClientHandler()
{
ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
};
return new HttpClient(httpMessageHandler);
},
ConnectionMode = ConnectionMode.Gateway
};
CosmosClient client = new CosmosClient(endpoint, authKey, cosmosClientOptions);
Older information
Reference:
https://github.com/Azure/azure-cosmos-dotnet-v3/issues/1551#issuecomment-634365001
https://learn.microsoft.com/en-us/azure/cosmos-db/local-emulator#running-on-mac-or-linux
Step 1 - Export the Certificate
Following this guide, but the certificate needs to be a PFX, not CRT. It will ask you to set some password.
Step 2 - Place the cert somewhere you can copy or access from docker
For example, I put it on a folder I can map to when booting Docker along with the code I wanted to run:
Step 3 - Get your machine's IP address
As per https://learn.microsoft.com/en-us/azure/cosmos-db/local-emulator#running-on-mac-or-linux, I used ipconfig and got my Windows IP.
Step 4 - Start a docker image
In my case, I use one with the NET Core 3.1 SDK, the official one from https://learn.microsoft.com/en-us/dotnet/architecture/microservices/net-core-net-framework-containers/official-net-docker-images
I started the container with an interactive shell, and mapping localhost to the IP I got on Step 3. This let's you use localhost in the connection string.
docker run -v /c/DockerSample:/DockerSample --add-host="localhost:192.168.1.15" -it mcr.microsoft.com/dotnet/core/sdk:3.1 /bin/bash
And I'm also mounting the folder where I saved the project and the certificate I want to import. This is not required, but I'm not fluent on Docker to know if there is a better way to pass the certificate.
After the shell starts, I basically run the commands described in the Emulator doc and the certificate gets added.
Step 5
The Docker container should now have the required Cert to connect to localhost and you should not need the HttpClientFactory.
NOTE: Also there is a bug tracking HttpClientFactory not being used everywhere that is the source of your error https://github.com/Azure/azure-cosmos-dotnet-v3/pull/1548
First of all, thank you to Matias Quaranta for all of the useful documentation. I had already pored over most of it before receiving his answer, but really appreciate all the time it took to compile it.
I have been struggling with this for around two weeks now and finally got something that I think will work. This work is largely based on the script found in this GitHub issue. I found that there is a PowerShell module that gets put on your computer when you install the Cosmos DB Emulator, so I tried to leverage those functions as much as possible to do the work.
The script's entry point is the function Start-CosmosDbEmulatorForDocker and it
Makes sure the Emulator is stopped.
Generates a new certificate to be used with the Docker image and replaces the one that was created upon install of the emulator.
Generates a .pfx certificate from the one created for the emulator.
Restarts the emulator once the new certificate is ready.
The password taken by the function is the one used for the .pfx file generated.
azureCosmosDbEmulator.ps1
using namespace System.ServiceProcess
Function Start-CosmosDbEmulatorForDocker(
[Parameter()]
[securestring]
$password
) {
$cosmosDbInstallLocation = Get-CosmosDbInstallLocation
If (!$cosmosDbInstallLocation) {
Install-AzureCosmosDBEmulator
}
Write-Host "Importing Microsoft.Azure.CosmosDB.Emulator powershell module."
Import-Module -Name "$($cosmosDbInstallLocation.InstallLocation)\PSModules\Microsoft.Azure.CosmosDB.Emulator"
Install-CosmosDBDockerCertificate -cosmosDbInstallLocation $cosmosDbInstallLocation.InstallLocation -password $password
Start-CosmosDbEmulator -AllowNetworkAccess -Key "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
}
Function Get-CosmosDbInstallLocation() {
Get-ChildItem HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall | ForEach-Object { Get-ItemProperty $_.PsPath } | Where-Object { $_.DisplayName -eq "Azure Cosmos DB Emulator" } | Select-Object InstallLocation
}
Function Install-AzureCosmosDBEmulator() {
Write-Host "Installing Azure Cosmos Db Emulator."
$installer = "$PSScriptRoot\cosmosEmulatorInstaller.msi"
curl "https://aka.ms/cosmosdb-emulator" -O $installer
Start-Process -Wait -FilePath msiexec -ArgumentList /i, $installer
Remove-Item $installer
}
Function Install-CosmosDBDockerCertificate(
[Parameter()]
[string]
$cosmosDbInstallLocation,
[Parameter()]
[securestring]
$password
) {
If ((Get-CosmosDbEmulatorStatus) -ne [ServiceControllerStatus]::Stopped) {
Write-Host "Stopping Cosmos DB emulator."
Stop-CosmosDbEmulator
}
$dockerCertificatesPath = Join-Path (Split-Path -Path $PSScriptRoot -Parent) "certificates"
$cosmosDbPfxCertificatePath = "$($dockerCertificatesPath)\cosmosdbemulator.pfx"
Uninstall-Certificate -dockerCertificatePath $cosmosDbPfxCertificatePath
Write-Host "Generating new Cosmos DB certificate to work with Docker."
New-CosmosDbEmulatorCertificate "host.docker.internal"
Start-Sleep -s 5
New-DockerCertificate -dockerCertificatePath $cosmosDbPfxCertificatePath -password $password
Set-Location (Split-Path -Path $PSScriptRoot -Parent)
}
Function Uninstall-Certificate(
[Parameter()]
[string]
$dockerCertificatePath
) {
Write-Host "Removing existing DocumentDbEmulatorCertificate certificate."
if (Test-Path $dockerCertificatePath) {
Remove-Item -Path $dockerCertificatePath
}
}
Function New-DockerCertificate(
[Parameter()]
[string]
$dockerCertificatePath,
[Parameter()]
[securestring]
$password
) {
Write-Host "Generating new pfx version of DocumentDbEmulatorCertificate certificate for use in Docker image."
Get-CosmosDbEmulatorCertificate | Export-PfxCertificate -Filepath $dockerCertificatePath -Password $password
}
I then have a shell script to be run inside the Docker image that will install the .pfx cert into the Docker container. The COSMOS_DB_EMULATOR_PFX_PASSWORD value must match the one used by the PowerShell script.
trust_cosmos_db_emulator_crt.sh
#!/bin/bash
# Save current working directory
PWD=`pwd`
pushd $PWD
# Find and move to the location of this script
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $DIR
if [ -n "$1" ]; then
COSMOS_DB_EMULATOR_PFX=$1
else
COSMOS_DB_EMULATOR_PFX="/certificates/cosmosdbemulator.pfx"
fi
COSMOS_DB_EMULATOR_PFX_PASSWORD="SUPER_SECRET_PASSWORD"
CERT_TO_TRUST="cosmosdbemulator.crt"
# Generate .crt file if pfx exists
if [ -f "$COSMOS_DB_EMULATOR_PFX" ]; then
openssl pkcs12 -in $COSMOS_DB_EMULATOR_PFX -clcerts -nokeys -out cosmosdbemulator.crt -passin pass:$COSMOS_DB_EMULATOR_PFX_PASSWORD;
fi
# # Trust Cert (will end located in /etc/ssl/certs/ based on *.crt name as a *.pem, e.g. /etc/ssl/certs/cosmosdbemulator.pem for cosmosdbemulator.crt)
if [ -f "$CERT_TO_TRUST" ]; then
cp $CERT_TO_TRUST /usr/local/share/ca-certificates/
update-ca-certificates
rm $CERT_TO_TRUST;
fi
# Restore working directory
popd
The project structure I have is as follows:
src/
scripts/
azureCosmosDbEmulator.ps1
trust_cosmos_db_emulator_crt.sh
certificates/
DockerFile
The Dockerfile contains the following lines:
COPY ["/scripts/", "/scripts/"]
COPY ["/certificates/", "/certificates/"]
RUN /scripts/trust_cosmos_db_emulator_crt.sh
With all of that in place, I can build the docker image with docker build -t temp . and then run it with docker run -it -p 80:80 temp and the code running inside of the docker container will talk to my local machine's installed version of the Azure Cosmos DB Emulator.
As this was a HUGE pain in the neck, if you are experiencing this pain as well, vote for better support from Microsoft on this here.

Setting environment variables in Flutter

For example, building a client for an API, like Twitch.
In a Dart CLI binary, I could use a generic environment variable, or a Dart definition variable. For example, using both as fallbacks:
main() {
String clientId =
// dart -dCLIENT_ID='abc bin/example.dart
// This is considered "compiled-into" the application.
const String.fromEnvironment('CLIENT_ID') ??
// CLIENT_ID='abc' dart bin/example.dart
// This is considered a runtime flag.
Platform.environment['CLIENT_ID'];
// Use clientId.
}
Does Flutter have a way of setting either/both of these, specifically...
During dev time
When shipped to prod
Happy to help with some docs once I figure out how :)
Starting from Flutter 1.17 you can define compile-time variables if you want to.
To do so just use --dart-define argument during flutter run or flutter build
If you need to pass multiple key-value pairs, just define --dart-define multiple times:
flutter run --dart-define=SOME_VAR=SOME_VALUE --dart-define=OTHER_VAR=OTHER_VALUE
and then, anywhere in your code you can use them like:
const SOME_VAR = String.fromEnvironment('SOME_VAR', defaultValue: 'SOME_DEFAULT_VALUE');
const OTHER_VAR = String.fromEnvironment('OTHER_VAR', defaultValue: 'OTHER_DEFAULT_VALUE');
Also, they can be used in native layers too.
Here is an article that explains more.
For configuration a common pattern I've seen is to use separate main files instead. i.e.
flutter run -t lib/production_main.dart
and
flutter build apk -t lib/debug_main.dart
And then in those different main files set up the configurations desired.
In terms of reading ids, you can do that from arbitrary assets https://flutter.io/assets-and-images/.
I believe it is possible in Flutter to read from the environment as you suggest, however I don't know how to set those environment variables on iOS or Android.
Since I was trying to solve this as well and encountered this thread I just wanted to add this for people looking for a solution in the future... If all you're looking for is PROD/DEV environments there is now a supported way of getting if the app is in production or not:
const bool isProduction = bool.fromEnvironment('dart.vm.product');
As suggested by:
https://twitter.com/FlutterDev/status/1048278525432791041
https://github.com/flutter/flutter/issues/4014
To run your app (in flutter run)
flutter run --dart-define=EXAMPLE_API_ENDPOINT=https://api.example.com/
To release your app (in flutter build)
My app wasn't letting users log in I realized that environment variables were empty strings in the app, instead of their actual values 😅.
iOS: flutter build ipa --dart-define=EXAMPLE_API_ENDPOINT=https://api.example.com/
Android: flutter build apk --dart-define=EXAMPLE_API_ENDPOINT=https://api.example.com/
--dart-define documentation
From the flutter run --help or flutter build ipa --help, the --dart-define shows:
Additional key-value pairs that will be available as
constants from the String.fromEnvironment, bool.fromEnvironment,
int.fromEnvironment, and double.fromEnvironment constructors.
Multiple defines can be passed by repeating "--dart-define"
multiple times.
I use simple shell script to generate dart defines. In my app there are 3 build flavors: dev, staging and prod. Environment variables were defined in a regular .env file.
env/
├── dev.env
├── prod.env
└── staging.env
Here is the script to generate dart-defines from .env file.
#!/bin/bash
# scripts/generate_dart_defines.sh
case "$1" in
"dev") INPUT="env/dev.env"
;;
"staging") INPUT="env/staging.env"
;;
"prod") INPUT="env/prod.env"
;;
*)
echo "Missing arguments [dev|staging|prod]"
exit 1
;;
esac
while IFS= read -r line
do
DART_DEFINES="$DART_DEFINES--dart-define=$line "
done < "$INPUT"
echo "$DART_DEFINES"
Here is the script to trigger a build.
#!/bin/bash
# build.sh
if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then
echo -e "Missing arguments: [apk|appbundle|ios] [release|debug|profile] [dev|staging|prod]"
# invalid arguments
exit 128
fi
DART_DEFINES=$(scripts/generate_dart_defines.sh $3)
if [ $? -ne 0 ]; then
echo -e "Failed to generate dart defines"
exit 1
fi
echo -e "artifact: $1, type: $2, flavor: $3\n"
echo -e "DART_DEFINES: $DART_DEFINES\n"
eval "flutter build $1 --$2 --flavor $3 $DART_DEFINES"
The script accepts 3 arguments. First one is the artifact apk, appbundle or ios. Second one is the build type release, debug or profile. Third one is the build flavor, dev, staging or prod.
./build.sh apk release prod
Please note that you also required to configure android and ios for different build flavors separately.
https://developer.android.com/studio/build/build-variants
https://shockoe.com/ideas/development/how-to-setup-configurations-and-schemes-in-xcode/
https://developer.apple.com/library/archive/documentation/ToolsLanguages/Conceptual/Xcode_Overview/ManagingSchemes.html
I do agree with the answer posted by #tatsuDn but I wanted to provide a solution that loads your environment variables from a .env file.
First create a .env file in the root folder of your project.
Ensure that you add the file to your pubspec.yaml and [git] ignore it.
Here is how your .env file should look
API_KEY=sampleapikey
# This line is a comment
# The white line above will be ignored
HEADER=sampleapiheader
ANOTHER_UNIQUE_KEY=theValueOfThisKey
KEY_CONTAINS_#=*234*5#
KEY_CONTAINS_EQUALS=IP8iwe=0&
Here is how your assets section to look like.
# To add assets to your application, add an assets section, like this:
assets:
- assets/images/
- assets/flags/
- .env
Finally, load your environment variable by reading and parsing the .env file to get a Map<String, String> that contains your key value pairs.
Future<Map<String, String>> parseStringToMap({String assetsFileName = '.env'}) async {
final lines = await rootBundle.loadString(assetsFileName);
Map<String, String> environment = {};
for (String line in lines.split('\n')) {
line = line.trim();
if (line.contains('=') //Set Key Value Pairs on lines separated by =
&&
!line.startsWith(RegExp(r'=|#'))) {
//No need to add emty keys and remove comments
List<String> contents = line.split('=');
environment[contents[0]] = contents.sublist(1).join('=');
}
}
return environment;
}
You can put a quick button in your code to test that the environment variables are being loaded properly.
ElevatedButton(
onPressed: () async {
final env = await parseStringToMap(assetsFileName: '.env');
print(env);
},
child: Text('Print Environment Variables')
),
Here is the output from the .env file above.
>>>I/flutter ( 7182): {API_KEY: sampleapikey, HEADER: sampleapiheader, ANOTHER_UNIQUE_KEY: theValueOfThisKey, KEY_CONTAINS_#: *234*5#, KEY_CONTAINS_EQUALS: IP8iwe=0&}
Notes: You will need to rerun the app (not hot reload) so that the .env assets is loaded.
You can also just load your variables in a json file[this may be helpful when you have non string environemental variables and you dont want to parse string.
To avaoid IO, it is a good Idea to just load the environment variables once and access them through out the app using service locators like GetIt.
although above answers are correct coming from python and reactjs I used dotenv and found the same for flutter to load .env file
https://pub.dev/packages/dotenv
Create a class:
import 'package:flutter/foundation.dart';
class AppUtils {
static String get clientId {
if (kDebugMode) return 'debug_id';
else if (kProfileMode) return 'profile_id';
else if (kReleaseMode) return 'production_id';
else if (kIsWeb) return 'web_mode_id';
throw ArgumentError('No mode detected');
}
}
Usage:
var id = AppUtils.clientId;

Add start up reg key without run the program

I coded a program, which start up on windows start up. My code is this:
public partial class Form1 : Form
{
RegistryKey reg = Registry.CurrentUser.OpenSubKey(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);//kanei autostart to programma sto anoigma tou upologisti
public Form1()
{
reg.SetValue("Computer Integrity", Application.ExecutablePath.ToString());//computer integrity is the reg key name
reg.Close();
InitializeComponent();
}
Now, the problem is that in order for the program to start, in windows start up, needs to open it first so the key will be registered in the "Registry editor". Is there a way to create a file(.bat for example) in order to register this key to the "registry editor", without needing to open the program ??
You may create the key in regisgry manually and then just export to yourfile.reg file:
https://technet.microsoft.com/en-us/library/cc755091.aspx
Then you can run the regedit from a command line:
regedit.exe /S yourfile.reg
You can also run such a commands from batch file directly via REG ADD command.
Refer here for details: Run reg command in cmd (bat file)?

how to use execute() in groovy to run any command

I usually build my project using these two commands from command line (dos)
G:\> cd c:
C:\> cd c:\my\directory\where\ant\exists
C:\my\directory\where\ant\exists> ant -Mysystem
...
.....
build successful
What If I want to do the above from groovy instead? groovy has execute() method but following does not work for me:
def cd_command = "cd c:"
def proc = cd_command.execute()
proc.waitFor()
it gives error:
Caught: java.io.IOException: Cannot run program "cd": CreateProcess error=2, The
system cannot find the file specified
at ant_groovy.run(ant_groovy.groovy:2)
Or more explicitly, I think binil's solution should read
"your command".execute(null, new File("/the/dir/which/you/want/to/run/it/from"))
According to this thread (the 2nd part), "cd c:".execute() tries to run a program called cd which is not a program but a built-in shell command.
The workaround would be to change directory as below (not tested):
System.setProperty("user.dir", "c:")
"your command".execute(null, /the/dir/which/you/want/to/run/it/from)
should do what you wanted.
Thanks Noel and Binil, I had a similar problem with a build Maven.
projects = ["alpha", "beta", "gamma"]
projects.each{ project ->
println "*********************************************"
println "now compiling project " + project
println "cmd /c mvn compile".execute(null, new File(project)).text
}
I got to fix the issue by running a command as below:
i wanted to run git commands from git folder, so below is the code which worked for me.
println(["git","add","."].execute(null, new File("/Users/xyz/test-org/groovy-scripts/$GIT_REPOS/")).text)
println(["git","commit","-m","updated values.yaml"].execute(null, new File("/Users/xyz/test-org/groovy-scripts/$GIT_REPOS/")).text)
println(["git","push","--set-upstream","origin","master"].execute(null, new File("/Users/xyz/test-org/groovy-scripts/$GIT_REPOS/")).text)

Resources