|
PROFESSIONAL NEWSGROUPS WINDEV, WEBDEV and WINDEV Mobile |
| | | | | |
Started by mateusdev, Jul., 17 2025 4:41 PM - 4 replies |
| |
| | | |
|
| |
Registered member 2 messages |
|
Posted on July, 17 2025 - 4:41 PM |
Bom dia, boa tarde ou boa noite, pessoal!
Estou com uma demanda de um cliente que deseja bloquear a captura de tela do aplicativo. Sei que no Android isso é possível utilizando uma função nativa da ferramenta (MyWindow.ScreenshotAllowed = False), o que resolve o problema por lá.
Porém, no iOS a Apple não permite o bloqueio direto de capturas de tela (print screen). Diante disso, gostaria de saber se existe alguma forma de detectar quando o usuário tira um print no iOS, mesmo que indiretamente — por exemplo, para que eu possa aplicar um efeito visual, como blur ou escurecimento temporário da tela após a detecção.
Se alguém tiver alguma dica ou já implementou algo semelhante, agradeço pela ajuda! |
| |
| |
| | | |
|
| | |
| |
Registered member 4,520 messages |
|
Posted on July, 17 2025 - 4:50 PM |
Bom dia
Coloca um botão na posição x -2000
Em description do botão
Hot key a combinação de teclas que faz a captura
Em Code
RETURN
1 linha de código
Simples assim!!!!
O botão está quente com o comando e o que vai fazer é nao Deixar acontecer !
Pog do Boller
-- Adriano José Boller ______________________________________________ Consultor e Representante Oficial da PcSoft no Brasil +55 (41) 99949 1800 adrianoboller@gmail.com skype: adrianoboller http://wxinformatica.com.br/ |
| |
| |
| | | |
|
| | |
| |
Registered member 4,520 messages |
|
Posted on July, 17 2025 - 6:32 PM |
Na windows do mobile Em Details Desmarcar Allow window screenshot
_José Willem_
-- Adriano José Boller ______________________________________________ Consultor e Representante Oficial da PcSoft no Brasil +55 (41) 99949 1800 adrianoboller@gmail.com skype: adrianoboller http://wxinformatica.com.br/ |
| |
| |
| | | |
|
| | |
| |
Registered member 4,520 messages |
|
Posted on July, 17 2025 - 7:22 PM |
No iOS, não é possível bloquear completamente o print screen (screenshot) devido às políticas de segurança da Apple, mas você pode implementar algumas medidas de proteção:
## 1. Detectar quando um screenshot foi tirado
```swift import UIKit
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Observador para detectar screenshots NotificationCenter.default.addObserver( self, selector: #selector(screenshotTaken), name: UIApplication.userDidTakeScreenshotNotification, object: nil ) } @objc func screenshotTaken() { // Ação quando screenshot é detectado showScreenshotAlert() // Você pode registrar o evento, enviar para analytics, etc. } func showScreenshotAlert() { let alert = UIAlertController( title: "Screenshot Detectado", message: "Por favor, não tire screenshots deste conteúdo sensível.", preferredStyle: .alert ) alert.addAction(UIAlertAction(title: "OK", style: .default)) present(alert, animated: true) } } ```
## 2. Ocultar conteúdo quando o app vai para background
```swift class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? private var overlayView: UIView? func sceneWillResignActive(_ scene: UIScene) { // Adiciona uma overlay quando o app vai para background addSecurityOverlay() } func sceneDidBecomeActive(_ scene: UIScene) { // Remove a overlay quando o app volta removeSecurityOverlay() } private func addSecurityOverlay() { guard let window = window else { return } overlayView = UIView(frame: window.bounds) overlayView?.backgroundColor = .white let label = UILabel() label.text = "Conteúdo Protegido" label.textAlignment = .center label.font = UIFont.systemFont(ofSize: 24, weight: .bold) label.translatesAutoresizingMaskIntoConstraints = false overlayView?.addSubview(label) window.addSubview(overlayView!) NSLayoutConstraint.activate([ label.centerXAnchor.constraint(equalTo: overlayView!.centerXAnchor), label.centerYAnchor.constraint(equalTo: overlayView!.centerYAnchor) ]) } private func removeSecurityOverlay() { overlayView?.removeFromSuperview() overlayView = nil } } ```
## 3. Proteger views específicas contra captura de tela
```swift extension UIView { func makeSecureAgainstScreenshots() { // Cria uma subview que não aparece em screenshots let field = UITextField() field.isSecureTextEntry = true field.isUserInteractionEnabled = false field.backgroundColor = .clear field.translatesAutoresizingMaskIntoConstraints = false self.addSubview(field) field.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true field.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true field.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true field.heightAnchor.constraint(equalTo: self.heightAnchor).isActive = true // Move o conteúdo para dentro do campo seguro field.layer.superlayer?.addSublayer(self.layer) } } ```
## 4. Implementação mais robusta com ViewController personalizado
```swift class SecureViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() setupSecurityMeasures() } private func setupSecurityMeasures() { // Detectar screenshots NotificationCenter.default.addObserver( self, selector: #selector(handleScreenshot), name: UIApplication.userDidTakeScreenshotNotification, object: nil ) // Detectar gravação de tela NotificationCenter.default.addObserver( self, selector: #selector(handleScreenRecording), name: UIScreen.capturedDidChangeNotification, object: nil ) } @objc private func handleScreenshot() { // Log do evento print("Screenshot detectado em: \(Date())") // Implementar sua lógica de segurança showSecurityWarning() } @objc private func handleScreenRecording() { if UIScreen.main.isCaptured { // Tela está sendo gravada showRecordingWarning() // Você pode ocultar conteúdo sensível aqui hidesSensitiveContent(true) } else { hidesSensitiveContent(false) } } private func showSecurityWarning() { // Implementar alerta ou ação de segurança } private func showRecordingWarning() { // Avisar sobre gravação de tela } private func hidesSensitiveContent(_ hide: Bool) { // Ocultar/mostrar conteúdo sensível view.subviews.forEach { $0.isHidden = hide } } deinit { NotificationCenter.default.removeObserver(self) } } ```
## Limitações importantes:
- **Não é possível bloquear completamente** screenshots no iOS por design da Apple - O iOS permite que usuários façam screenshots para acessibilidade - Apps não podem interferir nas funcionalidades básicas do sistema - Estas são medidas de **detecção e dissuasão**, não bloqueio absoluto
## Alternativas complementares:
1. **Watermarks** em conteúdo sensível 1. **Expiração** de conteúdo após tempo determinado 1. **Autenticação** adicional para acessar dados sensíveis 1. **Logs de auditoria** quando screenshots são detectados
Essas implementações ajudam a proteger conteúdo sensível, mesmo que não possam bloquear completamente os screenshots no iOS.
Teste com procedimento swift não WL. No canto superior mude de WL para Swift na code da procedure, Teste em linguagem nativa esses códigos acima.
Bons estudos
Forte abraço
-- Adriano José Boller ______________________________________________ Consultor e Representante Oficial da PcSoft no Brasil +55 (41) 99949 1800 adrianoboller@gmail.com skype: adrianoboller http://wxinformatica.com.br/ |
| |
| |
| | | |
|
| | |
| |
Registered member 4,520 messages |
|
Posted on July, 17 2025 - 7:42 PM |
O Windev Mobile permite integrar código Swift nativo em projetos iOS através de várias técnicas. Aqui estão as principais abordagens:
## 1. Chamadas de Funções Swift via iOSAppelFonctionSwift()
```windev // No Windev Mobile - chamando função Swift PROCÉDURE ChamarFuncaoSwift()
// Chamada simples sResultado é string = iOSAppelFonctionSwift("MinhaFuncaoSwift", "parametro1", 123)
// Chamada com múltiplos parâmetros nValor é numeric = iOSAppelFonctionSwift("CalcularValor", 10, 20, 30)
// Retorno de objeto JSON sJSON é string = iOSAppelFonctionSwift("ObterDadosComplexos", "chave") stDados é Variant = JSONVersStructure(sJSON) ```
```swift // Arquivo Swift nativo (ex: Funcoes.swift) @objc public class FuncoesNativas: NSObject { @objc public static func MinhaFuncaoSwift(_ param1: String, _ param2: Int) -> String { return "Resultado: \(param1) - \(param2)" } @objc public static func CalcularValor(_ a: Int, _ b: Int, _ c: Int) -> Int { return a + b + c } @objc public static func ObterDadosComplexos(_ chave: String) -> String { let dados = [ "chave": chave, "timestamp": Date().timeIntervalSince1970, "status": "sucesso" ] do { let jsonData = try JSONSerialization.data(withJSONObject: dados) return String(data: jsonData, encoding: .utf8) ?? "{}" } catch { return "{\"erro\": \"Falha na serialização\"}" } } } ```
## 2. Integração com Frameworks iOS Nativos
```swift // Framework para Camera/Fotos @objc public class CameraManager: NSObject { @objc public static func abrirCamera() -> String { DispatchQueue.main.async { let picker = UIImagePickerController() picker.sourceType = .camera if let rootVC = UIApplication.shared.windows.first?.rootViewController { rootVC.present(picker, animated: true) } } return "camera_aberta" } @objc public static func verificarPermissaoCamera() -> Bool { return AVCaptureDevice.authorizationStatus(for: .video) == .authorized } }
// Framework para Localização @objc public class LocationManager: NSObject, CLLocationManagerDelegate { private let locationManager = CLLocationManager() private var callback: String = "" @objc public static func obterLocalizacao(_ callbackWD: String) -> String { let manager = LocationManager() manager.callback = callbackWD manager.startLocationUpdates() return "solicitacao_enviada" } private func startLocationUpdates() { locationManager.delegate = self locationManager.requestWhenInUseAuthorization() locationManager.startUpdatingLocation() } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { guard let location = locations.last else { return } let dados = [ "latitude": location.coordinate.latitude, "longitude": location.coordinate.longitude, "precisao": location.horizontalAccuracy ] // Chama procedimento WinDev if let jsonData = try? JSONSerialization.data(withJSONObject: dados), let jsonString = String(data: jsonData, encoding: .utf8) { // Enviar de volta para WinDev via callback NotificationCenter.default.post(name: .locationUpdated, object: jsonString) } } } ```
## 3. Uso de Delegates e Callbacks
```windev // Procedimento WinDev para receber callbacks PROCÉDURE ReceberCallback(sResultado string) Info("Resultado recebido: " + sResultado) ```
```swift // Extensão para NotificationCenter extension Notification.Name { static let locationUpdated = Notification.Name("locationUpdated") static let cameraResult = Notification.Name("cameraResult") }
@objc public class CallbackManager: NSObject { @objc public static func configurarObservadores() { NotificationCenter.default.addObserver( forName: .locationUpdated, object: nil, queue: .main ) { notification in if let resultado = notification.object as? String { // Chamar procedimento WinDev self.chamarWinDev("ReceberCallback", com: resultado) } } } private static func chamarWinDev(_ procedimento: String, com parametro: String) { // Implementação específica para chamar WinDev // Usar bridge nativo do WinDev Mobile } } ```
## 4. Integração com APIs iOS Específicas
```swift // Biometria e Touch ID / Face ID @objc public class BiometriaManager: NSObject { @objc public static func verificarBiometriaDisponivel() -> String { let context = LAContext() var error: NSError? if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) { switch context.biometryType { case .faceID: return "faceid_disponivel" case .touchID: return "touchid_disponivel" default: return "biometria_nao_disponivel" } } return "erro_verificacao" } @objc public static func autenticarBiometria(_ mensagem: String) { let context = LAContext() context.evaluatePolicy( .deviceOwnerAuthenticationWithBiometrics, localizedReason: mensagem ) { success, error in DispatchQueue.main.async { let resultado = success ? "sucesso" : "falha" NotificationCenter.default.post( name: .biometriaResult, object: resultado ) } } } }
// Keychain para armazenamento seguro @objc public class KeychainManager: NSObject { @objc public static func salvarDados(_ chave: String, _ valor: String) -> Bool { let dados = valor.data(using: .utf8)! let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: chave, kSecValueData as String: dados ] SecItemDelete(query as CFDictionary) let status = SecItemAdd(query as CFDictionary, nil) return status == errSecSuccess } @objc public static func lerDados(_ chave: String) -> String { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: chave, kSecReturnData as String: true, kSecMatchLimit as String: kSecMatchLimitOne ] var result: AnyObject? let status = SecItemCopyMatching(query as CFDictionary, &result) if status == errSecSuccess, let data = result as? Data, let string = String(data: data, encoding: .utf8) { return string } return "" } } ```
## 5. Configuração no Projeto WinDev Mobile
```windev // Inicialização no projeto PROCÉDURE InicializarSwift()
// Configurar observadores Swift iOSAppelFonctionSwift("CallbackManager.configurarObservadores")
// Verificar recursos disponíveis sBiometria est string = iOSAppelFonctionSwift("BiometriaManager.verificarBiometriaDisponivel") Info("Biometria disponível: " + sBiometria)
// Procedimento para usar câmera PROCÉDURE UsarCamera() sResultado est string = iOSAppelFonctionSwift("CameraManager.abrirCamera")
// Procedimento para salvar dados seguros PROCÉDURE SalvarDadosseguros(sChave string, sValor string) bSucesso est boolean = iOSAppelFonctionSwift("KeychainManager.salvarDados", sChave, sValor) SI PAS bSucesso ENTÃO Erreur("Falha ao salvar dados no Keychain") FIM ```
## 6. Considerações Importantes
### Configuração do Bridging Header
```objective-c // WinDev-Bridging-Header.h #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> #import <AVFoundation/AVFoundation.h> #import <CoreLocation/CoreLocation.h> #import <LocalAuthentication/LocalAuthentication.h> ```
### Info.plist Necessário
```xml <key>NSCameraUsageDescription</key> <string>App precisa acessar a câmera</string> <key>NSLocationWhenInUseUsageDescription</key> <string>App precisa acessar localização</string> <key>NSFaceIDUsageDescription</key> <string>App usa Face ID para autenticação</string> ```
## 7. Debugging e Tratamento de Erros
```swift @objc public class DebugManager: NSObject { @objc public static func logDebug(_ mensagem: String) { #if DEBUG print("WinDev Swift Debug: \(mensagem)") #endif } @objc public static func tratarErro(_ erro: String) -> String { let errorInfo = [ "timestamp": Date().timeIntervalSince1970, "erro": erro, "plataforma": "iOS" ] do { let jsonData = try JSONSerialization.data(withJSONObject: errorInfo) return String(data: jsonData, encoding: .utf8) ?? "{}" } catch { return "{\"erro_critico\": true}" } } } ```
Essas técnicas permitem aproveitar todo o poder do iOS nativo dentro do Windev Mobile, mantendo a simplicidade do desenvolvimento WX enquanto acessa recursos avançados da plataforma.
Essas informações não estão no Help, mas pessoas que já programaram só com o Xcode sabem dessas camadas e aqui estou deixando explícito e também no https://forum.pcsoft.fr
-- Adriano José Boller ______________________________________________ Consultor e Representante Oficial da PcSoft no Brasil +55 (41) 99949 1800 adrianoboller@gmail.com skype: adrianoboller http://wxinformatica.com.br/ |
| |
| |
| | | |
|
| | | | |
| | |
| | |
| |
|
|
|