sexta-feira, 11 de dezembro de 2015

Ionic - SQLite no browser

Tentando usar o plugin do SQLite (do Cordova) com o Ionic eu tive o seguinte erro:

Uncaught TypeError: Cannot read property 'openDatabase' of undefined

Isso acontece, pois o plugin usa código nativo para utilizar o SQLite, então não funciona no browser... Para resolver alterei o código q abre a conexão com o banco.

De:

var db = null;
db = $cordovaSQLite.openDB("myapp.db");

Para:

var db = null;
if(window.cordova) {
    // used in cell phones
    db = $cordovaSQLite.openDB("myapp.db");
} else {
    // used in web browsers
   db = window.openDatabase("myapp.db", "1.0", "MyApp", -1);
}

Pronto, agora consigo utilizar no browser.

Todos os outros comandos continuam idênticos.

Fonte: http://stackoverflow.com/questions/30160552/ionic-framework-sqlite-testing-with-browser

Para estudar SQLite com ionic:
http://ngcordova.com/docs/plugins/sqlite/
https://blog.nraboy.com/2014/11/use-sqlite-instead-local-storage-ionic-framework/

Abraço!
Adriano Schmidt


quinta-feira, 3 de dezembro de 2015

Lista de imagens em Ionic

Faaala galera,

Tô trabalhando em projeto com Ionic para desenvolver uma app mobile híbrida e precisei exibir uma lista de imagens colocando 4 imagens por linhas...

Segue abaixo o código:

    <div ng-repeat="myObject in myList">
        <div class="row" ng-if="$index % 4 === 0">
            <div class="col col-25" ng-repeat="obj in [myList[$index], myList[$index + 1], myList[$index + 2], myList[$index + 3]]">
                 <img ng-src="{{obj.imgSrc}}" style="width: 100%;" />
            </div>
        </div>
    </div>

Para fazer isso me baseei nesse exemplo:

   <div ng-repeat="number in numbers"> 
        <div class="row" ng-if="$even">
            <div class="col col-50" ng-repeat="num in [numbers[$index],numbers[$index + 1]]">
                {{num}}
            </div>
        </div>
    </div>

Fonte: http://stackoverflow.com/questions/26688086/create-row-every-after-2-item-in-angular-ng-repeat-ionic-grid

Abraço!
Adriano Schmidt

quarta-feira, 4 de novembro de 2015

Instalar postgresql no ubuntu

Para instalar o postgresql no ubuntu vamos instalar também o pgadmin (cliente e gerenciador do postgres).

O pgadmin vamos instalar via interface gráfica:
- Procure por ubuntu software center na pesquisa do ubuntu
- Procure por pgadmin e o instale

Agora vá em um terminal e digite o comando abaixo para instalar o postgres
sudo apt-get install postgresql

Depois digite o comando abaixo para acessar o postgres que foi instalado utilizando o usuario default
sudo -u postgres psql

Depois altere a senha do usuário default:
ALTER USER postgres PASSWORD 'postgres';

Aperte Ctrl+D para sair do terminal psql

Agora volte no pgadmin, adicione uma nova conexão com localhost 5432 user postgres senha postgres

Pronto :D

Abraço!
Adriano Schmidt

Error: pg_config executable not found

Peguei um projeto com backend em phyton... e quando rodei o comando "pip install" deu o erro:

Collecting psycopg2 (from django-toolbelt==0.0.1->-r requirements.txt (line 7))
  Downloading psycopg2-2.6.1.tar.gz (371kB)
    100% |################################| 372kB 652kB/s
    Complete output from command python setup.py egg_info:
    running egg_info
    creating pip-egg-info\psycopg2.egg-info
    writing pip-egg-info\psycopg2.egg-info\PKG-INFO
    writing top-level names to pip-egg-info\psycopg2.egg-info\top_level.txt
    writing dependency_links to pip-egg-info\psycopg2.egg-info\dependency_links.txt
    writing manifest file 'pip-egg-info\psycopg2.egg-info\SOURCES.txt'
    warning: manifest_maker: standard file '-c' not found

    Error: pg_config executable not found.

    Please add the directory containing pg_config to the PATH
    or specify the full executable path with the option:

        python setup.py build_ext --pg-config /path/to/pg_config build ...

    or with the pg_config option in 'setup.cfg'.

    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in C:\Users\Adriano\AppData\Local\Temp\pip-build-ihjedt2y\psycopg2

Eu já tinha o PostgreSQL instalado, caso você não tenha, instale-o.
Depois adicione no PATH (variável de ambiente) a pasta bin que fica dentro da pasta de instalação do PostgreSQL

Pronto, rode de novo o comando e funcionará :)

quarta-feira, 21 de outubro de 2015

Como pegar a localização atual no Android?

Hoje precisei fazer uma app que usava a localização atual, é muito simples!

O projeto inteiro está aqui: https://github.com/adrianoschmidt/android-location-sample

Mas o segredo está nesta classe: MainActivity.java

Basicamente você tem q seguir esses 6 passos:

1) Sua Activity deve implementar as classes GoogleApiClient.ConnectionCallbacks e GoogleApiClient.OnConnectionFailedListener

    public class MainActivity extends Activity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

2) Criar um atributo do tipo GoogleApiClient

    private GoogleApiClient googleApiClient;

3) No onCreate ou na chamada de um botão você deve verificar se está tudo certo com a API que pega a localização e se estiver construir a API e se conectar nela.

        if (this.checkIfGooglePlayServicesAreAvailable()) {
            this.buildGoogleApiClient();
            this.mGoogleApiClient.connect();
        }

Verificando:

    private boolean checkIfGooglePlayServicesAreAvailable() {
        int errorCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        if (errorCode != ConnectionResult.SUCCESS) {
            System.out.println("GooglePlayServices errorCode: " + errorCode);
            GooglePlayServicesUtil.getErrorDialog(errorCode, this, 0).show();
            return false;
        }
        return true;
    }


4) Implementar o método onConnected e pegar a localicação (aqui no exemplo seto em dois TextViews que tenho na minha tela)

    @Override
    public void onConnected(Bundle bundle) {
        TextView textViewLatitude = (TextView) findViewById(R.id.textViewLatitude);
        TextView textViewLongitude = (TextView) findViewById(R.id.textViewLongitude);

        Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
        if (mLastLocation != null) {
            textViewLatitude.setText("Lat: " + String.valueOf(mLastLocation.getLatitude()));
            textViewLongitude.setText("Lng: " + String.valueOf(mLastLocation.getLongitude()));
        }
    }

5) Implementar os métodos de suspensão e de falha:

    @Override
    public void onConnectionSuspended(int i) {
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
    }

6) Solicitar a permissão no manifest

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

Basicamente é isso, qualquer coisa baixe o projeto no github ou comenta aqui no post.

Abraço!
Adriano Schmidt

quinta-feira, 15 de outubro de 2015

count com distinct

Opa..

Se eu faço uma query com distinct:

SELECT distinct o FROM tabela1 o JOIN tabela2

Quando eu faço count dela não vai bater:

SELECT distinct count (o) FROM tabela1 o JOIN tabela2

Pra resolver posso fazer assim:

SELECT count (distinct o) FROM tabela1 o JOIN tabela2

Obrigado ao meu chará Adriano de Souza pela dica!

Abraço!
Adriano Schmidt

Atalhos IntelliJ

Opa :)

Eu uso o Eclipse desde sempre... então quando fui usar o IntelliJ IDEA para desenvolver para Android (Android Studio) eu me perdia nos atalhos... então fiz essa tabelinha com os principais atalhos para não me perder :D

O quê 
Eclipse 
IntelliJ 
Deleta a linha 
Ctrl+D 
Ctrl+Y 
Procura por arquivo 
Ctrl+shift+R 
Ctrl+shift+N 
Troca linha de lugar 
Shift+Up/Down 
Alt+shift+Up/Down 
Duplica a linha 
Ctrl+shift+Down 
Ctrl+D 
Navegar entre abas 
Ctrl+PgUp/PgDn 
Alt+Left/Right 
Organizeimports 
Ctrl+Shift+O 
Ctrl+alt+O 
Format 
Ctrl+sfhit+F 
Ctrl+alt+L 

Tem algum atalho que você acha que devia estar nessa lista? Comenta aí :)

Abraço!!
Adriano Schmidt

segunda-feira, 12 de outubro de 2015

Executar comandos linux no Android

Fala galera, precisei executar comandos linux pela minha app Android, para isso usei o código abaixo.

Troque o "date" que é o comando para pegar a data da máquina pelo comando que você quer executar.

No final deste exemplo, peguei o valor retornado e o mostrei em um TextView.

        try {
            String commandLine = "date";
            Process process = Runtime.getRuntime().exec(commandLine);
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String value = bufferedReader.readLine();

            TextView dateTextView = (TextView) findViewById(R.id.text_info_line_6);
            dateTextView.setText(value);
        } catch (IOException e) {
            e.printStackTrace();
        }

No GitHub: https://gist.github.com/adrianoschmidt/8c83f972c20358a098a4

Caso você não queira fazer isso programaticamente pode usar o ADB Shell https://developer.android.com/tools/help/shell.html
É bem simples, basta acessar o terminal e ir até a pasta plataform-tools dentro da pasta do SDK do Android "cd <sdk_folder>\platform-tools"
Digite "adb devices" e tendo um dispositivo na lista basta digitar "adb shell" e você já pode digitar os comandos linux.

Vaaleu!
Adriano Schmidt

domingo, 11 de outubro de 2015

Android NDK - Hello World

O NDK é o Native Devolpment Kit e permite você escrever para android usando código nativo através de C ou C++

Geralmente se faz isso para obter mais performance (como é necessário no desenvolvimento de jogos por exemplo)

Mais detalhes em: https://developer.android.com/ndk/index.html

Eu estou usando para ver se consigo acessar recursos de telefonia para fazer uma conference... Mas enfim, segue um Hello World:

Faça o download do NDK: https://developer.android.com/ndk/downloads/index.html

Crie um novo projeto normalmente (File > New > New Project > dê um nome/domínio > Next > Next > Blank/Empty Activity > Finish)

No arquivo local.properties adicione uma linha com o caminho do seu NDK:

        ndk.dir=C\:\\android\\ndk\\android-ndk-r10e

No arquivo gradle.properties adicione isso:
android.useDeprecatedNdk=true

No arquivo build.gradle (da app) adicione em defaultConfig isso:

        ndk {
            moduleName "MyLib"
        }

Verifique se a MainActivity está estendendo diretamente a classe Activity, se não estiver, ajuste.

Na sua activity crie um método assim:
public native String getStringFromNative();

Vá em Build > Make

Depois vá no Terminal do Android Visual Studio e rode esse comando:

cd app\src\main

Depois rode esse comando (Não esquece de trocar as partes em negrito):

javah -d jni -classpath C:\android\sdk\platforms\android-23\android.jar;..\..\build\intermediates\classes\
debug br.com.localhost8080.ndksample.MainActivity

Isso vai criar uma pasta chamada jni com um arquivo .h nela

Crie nessa pasta jni um arquivo chamado main.c com o conteúdo abaixo (não esqueça de trocar os br_com_localhost8080_ndksample_MainActivity)

#include "br_com_localhost8080_ndksample_MainActivity.h"

JNIEXPORT jstring JNICALL Java_br_com_localhost8080_ndksample_MainActivity_getStringFromNative
        (JNIEnv * env, jobject obj)
  {
    return (*env)->NewStringUTF(env, "Hello from JNI!");
  }

Cria na mesma pasta um arquivo vazio chamado util.c (isso é necessário pois sem ele dá bug no gradle)

Depois dê um Build > Make

No activity_main.xml adicione um id no TextView:

android:id="@+id/my_textview"

Coloque na sua Activity

    static {
        System.loadLibrary("MyLib");
    }

No final do onCreate coloque:

        TextView tv = (TextView) findViewById(R.id.my_textview);
        tv.setText(getStringFromNative());

Dê um play e veja seu lindo HelloWorld escrito em C



Fontes no meu github: https://github.com/adrianoschmidt/ndk-sample

Para fazer esse hello world eu segui esse vídeo-tutorial (eh um pouco antigo, então peguei uns bugs que não apareceram no vídeo, e está em inglês): https://software.intel.com/en-us/videos/using-the-ndk-with-android-studio

Abraço!
Adriano Schmidt

Permissions no Android

Pessoal, hoje, na minha app Android, eu estava tentando fazer uma ligação. Dessa forma:

    private void callPhone() {
        Intent intent = new Intent(Intent.ACTION_CALL);
        intent.setData(Uri.parse("tel:456"));
        startActivity(intent);
    }


Mas deu o erro:

Caused by: java.lang.SecurityException: Permission Denial: starting Intent { act=android.intent.action.CALL dat=tel:xxx cmp=com.android.server.telecom/.components.UserCallActivity } from ProcessRecord{3e464e1 3861:br.com.localhost8080.myapp/u0a62} (pid=3861, uid=10062) requires android.permission.CALL_PHONE

Então fui no AndroidManifest.xml e coloquei a permission:

        <uses-permission android:name="android.permission.CALL_PHONE"/>


Mas aí aconteceu o erro:

Caused by: java.lang.SecurityException: Permission Denial: starting Intent { act=android.intent.action.CALL dat=tel:xxx cmp=com.android.server.telecom/.components.UserCallActivity } from ProcessRecord{ea870e6 4476:br.com.localhost8080.myapp/u0a62} (pid=4476, uid=10062) with revoked permission android.permission.CALL_PHONE

Para resolver usei o código abaixo pois a permission CALL_PHONE é level dangerous e você precisa solicitar permissao para o usuário:

    private static final int MY_PERMISSIONS_REQUEST_CALL_PHONE = 1;

    public void onClick(View view) {
        int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE);
        if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, MY_PERMISSIONS_REQUEST_CALL_PHONE);
        } else {
            callPhone();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_CALL_PHONE: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    callPhone();
                }
            }
        }
    }

    private void callPhone() {
        Intent intent = new Intent(Intent.ACTION_CALL);
        intent.setData(Uri.parse("tel:456"));
        startActivity(intent);
    }

Mais detalhes sobre permissões no android: https://developer.android.com/training/permissions/index.html

Mais detalhes sobre esse processo de ter que solicitar permissões: https://developer.android.com/training/permissions/requesting.html

sexta-feira, 9 de outubro de 2015

InfoQ - WildFly Avançado

Fala galera... esse ano palestrei no TDC Floripa sobre WildFly... mostrei um ambiente com cluster.. load balancer... entre outras coisas...

Essa semana o vídeo foi publicado na InfoQ, quem quiser dar uma olhadinha tá aí: www.infoq.com/br/presentations/wildfly-avancado




Obrigado a todos do JBug Brasil!!

Abraço!
Adriano Schmidt

quarta-feira, 7 de outubro de 2015

Map e Reduce em JavaScript

Para quem é do mundo JavaScript isso que vou mostrar é básico, mas quem é programador Java e precisou fazer isso em JavaScript com certeza tentou fazer um for... Vamos lá:

----------------

Imagine que você tenha uma lista de objetos... e cada objeto tenha um atributo chamado id... como você faria para obter uma nova lista com apenas com os ids?

Assim:

var idList = list.map(function(entity) {
    return entity.id;
});

----------------

Imagine que você tenha uma lista de objetos... e cada objeto tenha um atributo chamado value... como você faria para obter a soma de todos os atributos value?

Assim:

var valueTotal = list.reduce(function(valueTotal, entity) {
    return valueTotal + entity.value;
}, 0);

----------------

ATUALIZADO: FILTER

Imagine que você tenha uma lista de objetos, e queira que excluir dessa lista todos os itens com id < 10 (ou qualquer outra condição). Só usar o filter:

var filteredList = list.filter(function(entity) {
     return entity.id > 10;
});


----------------

Fontes no github: https://gist.github.com/adrianoschmidt/702dc06d9d7321600fb8

----------------

Vaaleu galera!
Adriano Schmidt

domingo, 27 de setembro de 2015

JavaScript no ServerSide com WildFly 10

Fala galera... fiz uns exemplos aqui pra testar a nova funcionalidade do WildFly 10 que permite que a gente escreva código JavaScript no Server Side \o) Criei alguns RESTs, um deles inclusive acessa um banco de dados e retorna o JSON....

Segue abaixo o código (github) e o passo-a-passo pra rodar aí na sua máquina.

Pré-requisitos:
- Java 8 instalado;
- Maven instalado;

Siga esses passos:
- Baixar e descompactar o WildFly 10
- Ir na pasta bin do WildFly e rodar o standalone.bat (no Windows) ou standalone.sh (no linux)
- Baixar esse projeto do github: https://github.com/adrianoschmidt/wildfly-js
- Abrir a pasta do projeto e rodar um "mvn clean install"
- Copiar o war gerado na pasta target do projeto e colar no <WildFly>/standalone/deployments
- Acessar via browser as seguintes URLs:

http://localhost:8080/wildfly-js/hello




http://localhost:8080/wildfly-js/hello/json




https://localhost:8080/wildfly-js/rest/members




Nesse post tem mais detalhes: http://wildfly.org/news/2015/08/10/Javascript-Support-In-Wildfly/

Abraço!!
Adriano Schmidt

Testar acesso JMX no WildFly

Fala pessoal,

Fiz uma classe Java para se comunicar com o JMX Client de um WildFly...

O fonte está no meu github:
https://github.com/adrianoschmidt/wildfly-jmx-client

Você pode usar isso caso precise mesmo acessar um JMX ou caso queira testar se ele está aberto ou não, esse foi meu caso. Em ambientes de produção é sempre interessante que ele não esteja visível.

Para usar a classe é só rodar ela normalmente pela IDE ou por linha de comando.

Repare nessas duas linhas:
String host = "localhost";
// String host = "192.168.0.35";

Com localhost, ao rodar na máquina onde está o WildFly deveria funcionar, pelo IP não deveria funcionar, pois por segurança não deveria estar disponível para acesso externo.

Para bloquear o acesso você pode fazer isso na sua infraestrutura ou no WildFly no stanalone.xml na seção interfaces.

Qualquer dúvida é só avisar!
Adriano Schmidt

terça-feira, 11 de agosto de 2015

JSON no Browser

Opa,

Se vc usa REST e ele retorna JSON... Instale essa extesion do chrome:

https://chrome.google.com/webstore/detail/jsonview/chklaanhfefbnpoihckbnefhakgolnmc?utm_source=chrome-app-launcher-info-dialog

Vai mudar suaa vida :D

Ela deixa formatadinho seu JSON... coisa linda!

Obrigado ao Guilherme Ribeiro pela dica!

Abraço!
Adriano Schmidt

domingo, 9 de agosto de 2015

node js - helloworld e um pouco mais

Semana passada comecei a brincar com Node JS.

Fiz um hello-world bem simples e rápido.

Caso queira fazer também, faça clone desse projeto e siga o arquivo README: https://github.com/adrianoschmidt/node-hello-world

Pronto, agora vamos um passo adiante.

No caso do Windows, depois vale à pena instalar mesmo o node (não só baixar o .exe e sim o .msi)

Agora instale o bower e o grunt
npm install -g bower
npm install -g grunt-cli

Baixe esse projeto e siga o README:
https://github.com/adrianoschmidt/seat-map-nodejs

Depois baixe o front-end desse seat-map (bootstrap, angular e grunt)
https://github.com/adrianoschmidt/seat-map-frontend

Qualquer dúvida é só comentar!

Abraço!
Adriano Schmidt

nome de arquivo muito longo no windows

Hoje tentei deletar uma pasta no Windows e aconteceu esse erro:

"Os nomes dos arquivos de origem são maiores do que o tamanho máximo permitido pelo sistema de arquivos."


Esse erro é causado pois o nome do caminho completo do arquivo é muito grande, mais do que o Windows suporta. No meu caso o npm criou umas pastas muito loucas no node_modules e aí gerou esse problema.

Para resolver faça o seguinte:

Alternativa 1) Renomear diretorios
Renomeie alguns diretorios, por exemplo:
Dê:
c:\work\projeto\node_modules\alguma coisa\outra coisa\diretorio com nome grande\mais uns 4 diretorios\arquivo.txt
Para:
c:\work\projeto\n\a\o\d\m\arquivo.txt

Assim o caminho do arquivo fica menor e tá tudo certo.

Alternativa 2) Mapear como unidade de rede

a) Faça uma pasta compartilhada
Você vai na pasta, talvez não na pasta mais interna, mas em alguma no meio do caminho e compartilha ela na rede (Botão direito na pasta > Compartilhar com)

b) Mapeie uma unidade de rede
Depois você tem que mapear essa pasta compartilhada como uma unidade de rede (Botão direito em Meu computador > Mapear unidade de rede > Escolhe a pasta compartilhada)

c) Exclua o arquivo
Ao acessar essa nova unidade (unidade "Z:" por exemplo) você vai conseguir excluir ou mover os arquivos pois agora o caminho completo do arquivo ficou menor.

-------------------

Qualquer dúvida é só comentar aí embaixo!!

Valeeu!!!
Adriano Schmidt

quinta-feira, 6 de agosto de 2015

Grunt com HTTPS/SSL em ambiente de desenvolvimento

Hoje precisei rodar o Grunt com HTTPS para fazer uns testes aqui. Segue o passo-a-passo:

Primeiro crie o certificado. Aqui estou usando o openssl no ubuntu. Se você usa Windows pesquise sobre como criar certificado no windows ( https://www.openssl.org/related/binaries.html )

openssl genrsa -out livereload.key 1024

openssl req -new -key livereload.key -out livereload.csr
(esse comando vai pedir alguns dados... vai preenchendo... Só em "Common Name" coloque "localhost" sem aspas)

openssl x509 -req -in livereload.csr -signkey livereload.key -out livereload.crt

Agora você tem 3 arquivos, copie os livereload.key e livereload.crt para dentro do seu projeto, na mesma pasta do Gruntfile por exemplo.
Eu criei uma pasta chamada ssl dentro da pasta onde está o Gruntfile.

----------------------

No seu Gruntfile no  "watch: {" você tem colocar esse options em todos os lugares que você quer que rode com https (no js, css e no livereload) por exemplo:

        options: {
            livereload: {
              port: 9000,
              key: grunt.file.read('ssl/livereload.key'),
              cert: grunt.file.read('ssl/livereload.crt')
            }
          }

Como ficou meu watch:

   watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all'],
        options: {
            livereload: {
              port: 9000,
              key: grunt.file.read('ssl/livereload.key'),
              cert: grunt.file.read('ssl/livereload.crt')
            }
          }
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'karma']
      },
      styles: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.css'],
        tasks: ['newer:copy:styles', 'autoprefixer'],
        options: {
            livereload: {
              port: 9000,
              key: grunt.file.read('ssl/livereload.key'),
              cert: grunt.file.read('ssl/livereload.crt')
            }
          }
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
     options: {
         livereload: {
           port: 9000,
           key: grunt.file.read('ssl/livereload.key'),
           cert: grunt.file.read('ssl/livereload.crt')
         }
       },
        files: [
          '<%= yeoman.app %>/{,*/}*.html',
          '.tmp/styles/{,*/}*.css',
          '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },


Agora no seu index.html, uma linha antes de fechar o body (</body>) cole isso:
<script>document.write('<script src="https://' + (location.host || 'localhost').split(':')[0] + ':9000/livereload.js"></' + 'script>')</script>

Pronto, ao rodar o "grunt serve --force" tudo estará rodando em HTTPS :)

Mais detalhes em: http://www.gilluminate.com/2014/06/10/livereload-ssl-https-grunt-watch/

Abraço! Qualquer dúvida comenta aí!
Adriano Schmidt

quarta-feira, 5 de agosto de 2015

X-Frame-Options to SAMEORIGIN

Eu estava fazendo um client OAUTH para fazer login via facebook e deu o erro:

Refused to display 'https://www.google.com.br/qualquerUrl' in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'.

Isso é problema de Same Origin Policy... uma política de segurança para evitar que scripts de um site acessem scripts de outro site. Mais em:
https://en.wikipedia.org/wiki/Same-origin_policy

Seguindo nessa linha instalei extensões no google chrome. Pesquisei por "cross domain" e achei várias. Mas não resolveu meu problema.

Iniciei o google chrome passando parâmetros para desabilitar a segurança. No Ubuntu fiz dessa forma:
google-chrome --disable-web-security --allow-file-access-from-files --allow-file-access --allow-cross-origin-auth-prompt
Mas não resolveu meu problema.

Achei que o erro estava acontecendo pois eu estava rodando em localhost ou 0.0.0.0 (estou usando grunt no meu projeto). Então tentei utilizar um DNS. Mas não resolveu meu problema.

Por fim, identifiquei, que minha empresa tinha um servidor de proxy, e por mais que minha máquina estivesse liberada e eu pudesse acessar tudo (pelo menos era o que parecia) verifiquei no network do chrome que o meu OAUTH Client acessava em algum momento a URL http://static.ak.facebook.com e o response vinha com uma página do google, e isso que gerava o erro.

Solução: Desligamos a máquina do proxy, não faz sentido hoje em dia usar isso :D E tudo funcionou perfeitamente \o)

Obrigado ao Herbert Smith e ao Alfredo Zipperer pela força!

Abraço!!!
Adriano Schmidt

quinta-feira, 30 de julho de 2015

Como instalar o Mongo no linux?

Segue passo-a-passo para instalar o MongoDB no Linux

Onde estiver escrito (root) você deve utilizar um usuário com permissão de root

Apenas para informacao: O mongo rodara em localhost:27017 e tambem sera startado automaticamente na proxima inicializacao da maquina.


########### Para RedHat/CentOS ###########

# crie o diretorio /data/db (root)
mkdir -p /data/db

# Garanta que o dono da pasta seja o usuario correto. (Altere <nome do usuario> para o usuario que iniciara o mongo) (root)
chown -R <nome do usuario> /data/db/

# crie o arquivo do repositorio yum (root)
vi /etc/yum.repos.d/mongodb-org-3.0.repo

# aperte i para entrar no modo "INSERT" e depois cole as seguintes linhas:
[mongodb-org-3.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.0/x86_64/
gpgcheck=0
enabled=1

# aperte "ESC" e depois digite ":wq" para salvar e fechar o arquivo

# agora instale o mongo (root)
yum install -y mongodb-org

# rode o comando abaixo e verifique se a instalação aconteceu com sucesso
mongo --version

# inicie o mongo
service mongod start

# teste
mongo

#apert ctrl c para sair


########### Para Ubuntu/Debian ###########


# crie o diretorio /data/db (root)
mkdir -p /data/db

# Garanta que o dono da pasta seja o usuario correto. (Altere <nome do usuario> para o usuario que iniciara o mongo) (root)
chown -R <nome do usuario> /data/db/

# agora instale o mongo (root)
apt-get install mongodb

# rode o comando abaixo e verifique se a instalação aconteceu com sucesso
mongo --version

# teste
mongo

#apert ctrl c para sair


Fonte: http://docs.mongodb.org/manual/tutorial/install-mongodb-on-red-hat/
Créditos: Ao Alfredo Zipperer que me deu uma mão para instalar o mongo aqui

Vaaleu!
Adriano Schmidt

terça-feira, 28 de julho de 2015

Unicode character table

Em algum momento da sua vida... seja num teste rápido ou até naquele momento de desespero... você vai precisar da tabela de Unicode...

Fiz esse post para registrar os caracteres mais usados e espero que possa ser útil para você assim como foi pra mim.


###### Unicode character table ######

#lettipo minusmaius
#a crase \u00E0 \u00C0
#a agudo \u00E1 \u00C1
#a chapeu \u00E2 \u00C2
#a ttil \u00E3 \u00C3
#c cedilha \u00E7 \u00C7
#e agudo \u00E9 \u00C9
#e chapeu \u00EA \u00CA
#i agudo \u00ED \u00CD
#o agudo \u00F3 \u00D3
#o chapeu \u00F4 \u00D4
#o ttil \u00F5 \u00D5
#u agudo \u00FA \u00DA


A lista completa pode ser encontrada aqui: http://unicode-table.com/en/

Fiz uma clase Java para printar esses caracteres para validar se estão corretos: https://gist.github.com/adrianoschmidt/60f0070b69e66067b922

Abraço!!!
Adriano Schmidt

segunda-feira, 27 de julho de 2015

Como trocar versão do Java no ubuntu?

Olá :)

No terminal, rode o comando "java -version" para ver a versão atual utilizada na sua máquina:







Rode o "sudo update-alternatives --config java" para ver as versões instaladas na sua máquina.
Como você usou o "sudo" talvez seja solicitado a senha do seu usuário.
Depois digite o número da coluna "Selection" de acordo com a versão que você que utilizar.















Depois rode o "java -version" de novo para verificar se funcionou:







É isso :)

Abraço!
Adriano Schmidt

terça-feira, 21 de julho de 2015

Spring OAP

Hoje precisei criar um interceptor.

Queria que antes e depois da execução de determinados métodos fosse chamado um Rest.
Também queria que se o método lançasse uma exception, chamasse outro Rest.

Pensei em annotation processor... orientação a aspectos com o aspectj... no fim resolvi com o Spring AOP.

Resumindo, você precisa:

Criar uma annotation para anotar no método que você quer interceptar.
Criar um Advisor para ler os métodos que tem a annotation.
Criar o interceptador para inserir o comportamento que você quer.
Alterar o applicationContext.xml e colocar o component-scan com o pacote onde está seu Advisor e adicionar o bean DefaultAdvisorAutoProxyCreator.

Com isso você consegue apenas colocando uma anotação no seu método fazer algo antes dele ser chamado, depois, ou tratar exceptions por exemplo.

Você pode ver o código nesse meu projeto no GitHub: https://github.com/adrianoschmidt/springaop

Mais detalhes em:
http://blog.javaforge.net/post/76125490725/spring-aop-method-interceptor-annotation

Abraço!!
Adriano Schmidt

Como fazer deploy no nexus

Para fazer seu projeto fazer deploy no nexus você precisa:

Criar repositórios no nexus:
Acesse o nexus como admin e crie dois repositórios do tipo "Hosted Repository"
Configure o "Repository Policy" do primeiro como "Release" e dê o nome de nome-do-projeto-releases
Configure o "Repository Policy" do segundo como "Snapshot" e dê o nome de nome-do-projeto-snapshots

Adicionar no seu pom: (altere a URL e o nome-do-projeto)
<distributionManagement>
<repository>
<id>nome-do-projeto-releases</id>
<url>http://nexus.localhost8080.com.br/nexus/content/repositories/nome-do-projeto-releases</url>
</repository>
<snapshotRepository>
<id>nome-do-projeto-snapshots</id>
<url>http://nexus.localhost8080.com.br/nexus/content/repositories/nome-do-projeto-snapshots</url>
</snapshotRepository>
</distributionManagement>

Configurar settings.xml
Configure o setting.xml (seja no maven da sua máquina ou no Jenkins (no jenkins você pode configurar pelo managed files também))

      <servers>
          <server>
              <id>nome-do-projeto-releases</id>
              <username>user_no_nexus_com_permissao_de_deploy</username>
              <password>senha_do_user</password>
          </server>
          <server>
              <id>nome-do-projeto-snapshots</id>
              <username>user_no_nexus_com_permissao_de_deploy</username>
              <password>senha_do_user</password>
          </server>
      </servers>


Deploy na mão
Abra o terminal e rode o comando: mvn clean deploy

Deploy pelo jenkins
Mesma coisa que manual, porém configure o seu job para fazer o mvn clean deploy


Abraço!!
Adriano Schmidt

segunda-feira, 15 de junho de 2015

O usuário está bêbado #01

Fala pessoal, finalmente fiz o primeiro vídeo do "O usuário está bêbado".

Se você ainda não conhece o projeto acesse: http://www.localhost8080.com.br/o-usuario-esta-bebado

Mas basicamente bebo muita cerveja e testo sites, apps ou sistemas em uma perspectiva de Usabilidade/UX e depois faço um vídeo e um relatório do que pode ser melhorado.

Segue abaixo o vídeo e o relatório:



Relatório - O usuário está bêbado - #01 - Site bebidaboa.com.br


O site testado foi o www.bebidaboa.com.br que de um modo geral apresenta uma boa usabilidade, inclusive mobile, e como qualquer site ou pessoa, tem pontos a melhorar. São eles:

Homepage

A sua homepage deve dar foco para explicar o que seu site é, o que ele oferece e quais são seus diferenciais.

Uma pessoa ao acessar o seu site, deve nos primeiros segundos identificar que é um site para bar tenders com receitas oficiais e dicas sobre drinks, etc.

Referências:
http://www.nngroup.com/articles/most-violated-homepage-guidelines/

Otimizar imagens

Percebi uma leve demora para a exibição das imagens no site, como o site tem muitas imagens é interessante utilizar uma ferramenta como o www.jpegmini.com para reduzir o tamanho (bytes) das imagens sem perder a qualidade.
Em imagens que sempre terão o mesmo tamanho (que não mudam de tamanho na exibição do celular e de um PC por exemplo) é interessante colocar fixo a largura e altura das imagens.

Referências:
http://browserdiet.com/pt/

Carrossel

Carrossel é um assunto que pode gerar muita discussão, existem vários artigos interessantes sobre isso, mas vou dar duas recomendações simples:
- Deixe o carrossel estático, ele deve ir para o lado apenas se o usuário clicar no botão para trocar de slide.
- Diminua os textos de cada slide do carrossel, seja mais sucinto, talvez apenas o título e imagem.

Motivos:
- O movimento do carrossel sem o comando do usuário pode irritá-lo;
- O usuário não tem tempo suficiente para ler toda a informação antes do carrossel se movimentar;
- Mesmo se for pouca informação, existem pessoas que leem mais devagar, que podem não entender uma palavra, ou por exemplo uma pessoa que não seja brasileira e demore mais tempo para ler um texto simples;
- Prejudica a acessibilidade pois usuários com determinadas deficiências podem ter dificuldade para conseguir pausar o carrossel ou clicar no “Leia Mais”;
- Usuários podem ignorar o carrossel por imaginarem que não conseguirão lê-lo a tempo.

No celular o carrossel não funcionou muito bem, as imagens estão muito grandes, os textos também e a navegação está um pouco confusa.

Referências:
http://www.nngroup.com/articles/auto-forwarding/
http://www.smashingmagazine.com/2015/02/09/carousel-usage-exploration-on-mobile-e-commerce-websites/

Esses dois artigos são bem interessantes, o primeiro não fala muito bem de carrossel e o segundo mostra um bom uso dele. A partir deles você obterá outras referências de artigos também.

Analisando o carrossel da amazon.com percebe-se que o carrossel se move automaticamente, porém, duas coisas são interessantes:
- O carrossel passa por todos os slides apenas uma vez, depois ele para no primeiro. Ele não fica se movendo eternamente.
- Os textos em cada slide são bem curtos.

Público alvo

Se o público alvo são apenas bar tenders profissionais, é preciso deixar claro isso logo ao entrar no site, pois um bar tender ao entrar no site pode achar que é só mais um site qualquer de receitas de bebidas, ele precisa perceber nos primeiros segundos ao entrar no site que pode encontrar muito conteúdo interessante ali.

Mas se também tem o interesse em focar em qualquer pessoa que esteja em casa e queira fazer uma bebida diferente, pessoas como:
- Universitários numa festa com amigos;
- Um divorciado de 30 anos que quer beber algo diferente com sua namorada;
- Uma mulher querendo servir uma bebida para as amigas;

Então você tem que pensar que essas pessoas não conhecem de bebida, então elas tem poucos ingredientes em casa por exemplo e não conhecem determinados termos.
É necessário melhorar os filtros e menus (isso até para bar tenders profissionais vai ajudar).
Outra coisa: Eu não encontrei o campo "Tipo de Medida" no meu primeiro teste para poder trocar para "Caseira". E mesmo na medida caseira, eu não sei quanto é 30 ml, talvez pensar em uma forma de facilitar isso.

No início do site poderia aparecer uma pergunta como "Quem é você?"
-Trabalho como bar tender ou estou estudando isso
-Quero aprender como fazer uma bebida legal em casa
E com base nessa pergunta você poderia alterar o site oferecendo uma experiência diferente para cada perfil.

Mas talvez você veja que não valeria o esforço, que o seu foco é bar tender e quem está estudando isso.
Às vezes uma pequena seção para quem não sabe nada poder estudar um pouco e ter o conhecimento base para navegar no site chamaria bastante atenção, talvez até mais do que preparar todo o site para quem não conhece muito do assunto.

Notícias

Colocar um link para algo relacionado dentro do site logo nos primeiros parágrafos da notícia funciona muito bem.

Seção “Destaque”

Retirar a seção de "destaque", pois:
-Parece que você está vendendo algo
-Parece spam, se você tiver como analisar, perceberá que quase ninguém clica
-Quanto mais informação na tela, maior a carga de trabalho

Referências:
www.nngroup.com/articles/banner-blindness-old-and-new-findings
Para um melhor entendimento, recomendo a leitura do artigo do Jacob Nielsen sobre “Banner Blindness” onde ele fala que usuários quase nunca olham para qualquer coisa que pareça um anúncio. Nessa imagem também mostrada no vídeo mostra que os usuários raramente olham para os anúncios:


Formulário de cadastro

O formulário está muito grande e isso dificulta que as pessoas cheguem até o fim, elas pode desistir de continuar o cadastro ao ver que o formulário é extenso ou desistir no meio caso qualquer coisa a distraia.

Campos como "Apelido", "Sexo", "Data de nascimento", "foto", todos os campos de endereço e números de telefone talvez não sejam necessários no primeiro cadastro. Possibilite o preenchimento desses dados em um outro momento.
Talvez retirar o campo "Profissão" e seguir a ideia do "Sou Bartender Profissional" e exibir 3 campos para seleção:
- Sou bartender profissional
- Quero ser um bartender
- Gosto de apreciar boas bebidas

Retire a seção de "Bebidas mais acessadas" do lado do formulário, isso pode distrair o usuário, além de que se o usuário clicar ali, ele sairá do cadastro sem finalizar o preenchimento.

Mobile

Não fiz uma análise muito aprofundada do mobile, apesar de ser muito importante, mas posso dar três dicas:
- Imagem do logo ocupa boa parte da tela, diminuir imagem ou talvez retirar;
- Carrossel dificultou a navegação, talvez para mobile exibir as notícias de outra forma, ou simplificar o carrossel.
- O menu é um pouco difícil de clicar, principalmente para quem tem o dedo mais gordinho como o Homer Simpson


Conclusão

Foi um prazer testar esse site e mais legal ainda ver que essas dicas estão sendo colocadas em prática.
O site oferece uma boa usabilidade, mas como qualquer site tem pontos a serem melhorados.
Eu recomendaria esse site a um amigo bartender e também para amigos que queiram fazer alguma bebida especial. Eu mesmo me tornarei usuário assíduo deste site.

Um grande abraço ao meu amigo Marcelo, o primeiro cliente do "O usuário está bêbado", todo sucesso do mundo e muitos usuários satisfeitos na sua vida!

Valeu galera!
Adriano Schmidt