كيف تحمي بيانات تطبيقك من السرقة عند الانتقال إلى الخلفية في Flutter ؟

كيف تحمي بيانات تطبيقك من السرقة عند الانتقال إلى الخلفية في Flutter ؟

كيفية إخفاء البيانات الحساسة في تطبيقات Flutter باستخدام Blur عند التشغيل في الخلفية

في بعض الأحيان، يمكن أن تحتوي شاشات التطبيقات على بيانات حساسة، مثل معلومات الدفع، والتي من الأفضل إخفاؤها أو حجبها عند تشغيل التطبيق في الخلفية للحفاظ على الخصوصية. في هذه المقالة، سنتعلم كيفية تنفيذ التشويش أو إخفاء هذه البيانات باستخدام Flutter وسنقدم لك الخطوات التي يجب اتباعها.مطلوب شرح مفصل.


لماذا يجب علينا إخفاء البيانات عند تشغيل التطبيق في الخلفية؟

عندما ينتقل أحد التطبيقات إلى الخلفية، قد تكون شاشة التطبيق مرئية مؤقتًا للمستخدمين الآخرين أو في عرض التطبيقات المفتوحة مؤخرًا. ويشكل ذلك تهديدًا للخصوصية، خاصة إذا كانت الشاشة تحتوي على معلومات حساسة مثل تفاصيل الدفع أو المعلومات الشخصية. الحل الأفضل هنا هو الاختباءقم بإعطاء أو استخدام تأثير التمويه لجعله غير قابل للقراءة.


كيف يمكنني تنفيذ هذه الوظيفة في Flutter؟

الخطوة 1: قم بإنشاء StatefulWidget لمراقبة دورة حياة التطبيقالخطوة الأولى هي إنشاء StatefulWidget لمراقبة حالة دورة حياة التطبيق. بفضل هذه الوظيفة، يمكننا معرفة متى يدخل التطبيق في الخلفية وبالتالي إخفاء البيانات عند الضرورة.

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
  bool _isInBackground = false;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    setState(() {
      _isInBackground = state == AppLifecycleState.paused;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Stack(
        children: [
          HomeScreen(),
          if (_isInBackground)
            Positioned.fill(
              child: Container(
                color: Colors.white,
                child: Center(
                  child: Text(
                    'App in Background',
                    style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
                  ),
                ),
              ),
            ),
        ],
      ),
    );
  }
}

الخطوة 2: مراقبة دورة حياة التطبيقفي هذه الخطوة، نستخدم WidgetsBindingObserver في فئة _MyAppState لتتبع حالة التطبيق. عندما يكون التطبيق في وضع الخلفية، تتغير حالة التطبيق إلى متوقف مؤقتًا، مما يسمح لنا بتحديد متى يجب أن تظهر شاشة الأمان.ا

لخطوة 3: إنشاء شاشة أمان عند تشغيل التطبيق في الخلفيةنستخدم Stack لعرض الشاشة الرئيسية للتطبيق وفي نفس الوقت نظهر الشاشة المظلمة أو المخفية أعلاه عندما يكون التطبيق في الخلفية. تمت إضافة حاوية بيضاء تحتوي على رسالة تفيد بوجود التطبيق في الخلفية. يمكنك استبدال هذه الشاشة بأي أداة تتوافق مع تصميم تطبيقك. 

الخطوة 4: إنشاء شاشة رئيسيةوأخيرًا، قم بإنشاء ملف HomeScreen. السهم الذي يمثل الشاشة الرئيسية للتطبيق. يحتوي هذا الملف على واجهة المستخدم الرئيسية التي سيتم إخفاؤها أو تعتيمها عندما ينتقل التطبيق إلى الخلفية.

import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home Screen'),
      ),
      body: Center(
        child: Text(
          'This is the home screen',
          style: TextStyle(fontSize: 24),
        ),
      ),
    );
  }
}

لماذا استخدام WidgetsBindingObserver؟

نحن نستخدم WidgetsBindingObserver لمراقبة حالة دورة حياة التطبيق لمعرفة متى ينتقل إلى الخلفية أو يعود إلى المقدمة. يساعدنا هذا في عرض واجهة الأمان عندما يكون التطبيق في الخلفية.

هل يؤثر هذا الحل البديل على الأداء؟

لا، لأننا نستخدم حاوية بسيطة لعرض شاشة الأمان. ولا يتطلب موارد نظام كبيرة، وبالتالي فإن التأثير على الأداء ضئيل.

هل يمكنني تخصيص الشاشة المخفية؟

بالطبع! يمكنك تخصيص قناع الشاشة حسب رغبتك، إما عن طريق إضافة تأثير التمويه أو عرض صورة مخصصة أو حتى إخفاء جزء معين من الشاشة. 

كيف يمكنك تحسين تجربة المستخدم؟

يمكنك تحسين تجربة المستخدم عن طريق إضافة المزيد من التأثيرات المرئية المتقدمة، مثل التمويه أو تظليل الشاشة الديناميكي.يمكن أن تساعد إضافة رسالة أو شعار واضح يشير إلى أن التطبيق يعمل في الخلفية في تحسين تجربة المستخدم وزيادة الثقة في أمان التطبيق.

الكود كامل
import 'dart:ui';

import 'package:flutter/material.dart';

class BalanceDetailsView extends StatefulWidget {
  const BalanceDetailsView({super.key});

  @override
  BalanceDetailsViewState createState() => BalanceDetailsViewState();
}

class BalanceDetailsViewState extends State<BalanceDetailsView> with WidgetsBindingObserver {
  bool _isAppInBackground = false;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    debugPrint('AppLifecycleState=============>>>>>>>>>>>>>>>: $state');
    if (state == AppLifecycleState.resumed) {
      // Trigger a rebuild after a delay
      setState(() {
        _isAppInBackground = false;
      });
    } else {
      setState(() {
        _isAppInBackground = true;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Balance Details'),
      ),
      body: Stack(
        children: [
          const Padding(
            padding: EdgeInsets.all(16.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                // ***********  Balance Overview ***********
                BalanceOverview(),
                SizedBox(height: 20),
                //*********** */ Recent Transactions ***********
                Text(
                  'Recent Transactions',
                  style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                ),

                RecentTransactions(),
              ],
            ),
          ),
          if (_isAppInBackground)
            Positioned.fill(
              child: BackdropFilter(
                filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
                child: Container(
                  color: Colors.black.withOpacity(0.5),
                ),
              ),
            ),
        ],
      ),
    );
  }
}

class RecentTransactions extends StatelessWidget {
  const RecentTransactions({
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    final transactions = [
      {'title': 'Payment to ABC Corp', 'amount': '-\$123.45', 'date': 'Aug 12'},
      {'title': 'Salary from XYZ Ltd', 'amount': '+\$2,500.00', 'date': 'Aug 10'},
      {'title': 'Coffee Purchase', 'amount': '-\$4.50', 'date': 'Aug 9'},
      {'title': 'Payment from John Doe', 'amount': '+\$150.00', 'date': 'Aug 8'},
    ];
    return Expanded(
      child: ListView.builder(
        itemCount: transactions.length,
        itemBuilder: (context, index) {
          final transaction = transactions[index];
          return ListTile(
            title: Text(transaction['title']!),
            subtitle: Text(transaction['date']!),
            trailing: Text(
              transaction['amount']!,
              style: TextStyle(
                color: transaction['amount']!.startsWith('+') ? Colors.green : Colors.red,
                fontWeight: FontWeight.bold,
              ),
            ),
          );
        },
      ),
    );
  }
}

class BalanceOverview extends StatelessWidget {
  const BalanceOverview({
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(16.0),
      decoration: BoxDecoration(
        color: Colors.blueAccent,
        borderRadius: BorderRadius.circular(8.0),
      ),
      child: const Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            'Total Balance',
            style: TextStyle(color: Colors.white, fontSize: 18),
          ),
          SizedBox(height: 8),
          Text(
            '\$12,345.67',
            style: TextStyle(
              color: Colors.white,
              fontSize: 36,
              fontWeight: FontWeight.bold,
            ),
          ),
        ],
      ),
    );
  }
}

تعليقات