커뮤니티
포인트
쿠폰
내 강의실
국비 신청 내역
증명서
계정
로그아웃
학습 질문
개발 일지
나의 활동
답변 완료
Android 설정 관련 문의
[왕초보] 플러터(Flutter)로 시작하는 앱개발 종합반 v0
5주차
북마크
진*만
댓글
12
추천
0
조회수
26
조회수
26
답변 완료

* 겪고 있는 문제 상황을 최대한 자세하게 작성해주세요.

* 문제 해결을 위해 어떤 시도를 해보았는지 구체적으로 함께 알려주세요.


안녕하세요? - 5주차. 구글 애드몹 배포(https://teamsparta.notion.site/5-0135de3fa406446b8949d1026a24953b#5bde890e8a9c4c2398eae0a83ddb29e9)에서 

단계적으로 진행하다가 2. Android 설정을 한 이후로 첨부한 이미지와 같은 에러가 뜹니다.

"You don't have an extension for debugging XML." ■■■■ 


확인 부탁 드립니다.

감사합니다. 

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


 2) AdMob 설치

 1. google_mobile_ads 설치

 PS D:\00_Prj\04_App\01_flutter\mymemo_admob> flutter pub add google_mobile_ads

 2. Android 설정

  - /AndroidManifest.xml 파일에 아래 내용 추가 ■■■■ 

  (D:\00_Prj\04_App\01_flutter\mymemo_admob\android\app\src\main)

   <meta-data

      android:name="com.google.android.gms.ads.APPLICATION_ID"

      android:value="ca-app-pub-6965675458210495~5186297668"/>

=============================================================================================================



스파르타 즉문즉답




작성한 코드 및 에러 메세지

import 'dart:io';


import 'package:flutter/cupertino.dart';

import 'package:flutter/material.dart';

import 'package:google_mobile_ads/google_mobile_ads.dart';

import 'package:provider/provider.dart';

import 'package:shared_preferences/shared_preferences.dart';


import 'memo_service.dart';


late SharedPreferences prefs;


void main() async {

  debugPrint("■ [/main.dart] [main()] ==> [T_01] [Project Start] ■■■");


  WidgetsFlutterBinding.ensureInitialized();

  prefs = await SharedPreferences.getInstance(); // 인스턴스 생성(shared_preferences 패키지)

  MobileAds.instance.initialize(); // 인스턴스 생성(MobileAds)


  runApp(

    MultiProvider(

      providers: [

        ChangeNotifierProvider(create: (context) => MemoService()), // MemoService 데이터 관리 class 호출

      ],

      child: const MyApp(), // MyApp class 호출

    ),

  );

}


class MyApp extends StatelessWidget {

  const MyApp({super.key});


  @override

  Widget build(BuildContext context) {

    debugPrint("■ [/MyApp.C] ==> [T_01] [MyApp Start]");


    return MaterialApp(

      debugShowCheckedModeBanner: false,

      home: HomePage(), // HomePage class 호출

    );

  }

}


// 홈 페이지

class HomePage extends StatefulWidget {

  const HomePage({super.key});


  @override

  State<HomePage> createState() => _HomePageState();

}


class _HomePageState extends State<HomePage> {

  final BannerAd myBanner = BannerAd(

    // Test 광고 ID, 광고 승인받은 후 생성한 광고 unit ID 로 바꾸기

    adUnitId: Platform.isAndroid

        ? 'ca-app-pub-3940256099942544/6300978111' // Android ad unit ID

        : 'ca-app-pub-3940256099942544/2934735716', // iOS ad unit ID

    size: AdSize.fullBanner,

    request: AdRequest(),

    listener: BannerAdListener(

      onAdFailedToLoad: (ad, error) {

        ad.dispose();

      },

    ),

  );


  @override

  void initState() {

    // 광고를 화면에 띄우기 위해서는 load 해오는 코드를 위젯을 처음 그려줄 때 실행

    // TODO: implement initState

    super.initState(); //기존에 initState 에 지정된 로직들을 실행


    myBanner.load(); // 배너 광고를 호출

  }


  @override

  Widget build(BuildContext context) {

    debugPrint("■ [/_HomePageState.C] ==> [T_01] [_HomePageState Start]");


    return Consumer<MemoService>(

      builder: (context, memoService, child) {

        // memoService로 부터 memoList 가져오기

        List<Memo> memoList = memoService.memoList;


        return Scaffold(

          appBar: AppBar(

            // 01. appBar 위젯■  =====================>

            title: Text("mymemo"),

          ), // 01. appBar 위젯■  =====================>

          body: memoList.isEmpty // 02. body 위젯■ =====================>

              ? Center(child: Text("메모를 작성해 주세요"))

              : ListView.builder(

                  itemCount: memoList.length, // memoList 개수 만큼 보여주기

                  itemBuilder: (context, index) {

                    Memo memo = memoList[index]; // index에 해당하는 memo 가져오기

                    return ListTile(

                      // 메모 고정 아이콘

                      leading: IconButton(

                        icon: Icon(CupertinoIcons.pin),

                        onPressed: () {

                          print('$memo : pin 클릭 됨');

                        },

                      ),

                      // 메모 내용 (최대 3줄까지만 보여주도록)

                      title: Text(

                        memo.content,

                        maxLines: 3,

                        overflow: TextOverflow.ellipsis,

                      ),

                      onTap: () {

                        // 아이템 클릭시

                        Navigator.push(

                          context,

                          MaterialPageRoute(

                            builder: (_) => DetailPage(

                              index: index,

                            ),

                          ),

                        );

                      },

                    );

                  },

                ), // 02. body 위젯■ =====================>

          floatingActionButton: FloatingActionButton(

            // 03. bottomNavigationBar 위젯■  =====================>

            child: Icon(Icons.add),

            onPressed: () {

              // + 버튼 클릭시 메모 생성 및 수정 페이지로 이동

              memoService.createMemo(content: '');

              Navigator.push(

                context,

                MaterialPageRoute(

                  builder: (_) => DetailPage(

                    index: memoService.memoList.length - 1,

                  ),

                ),

              );

            },

          ), // 03. bottomNavigationBar 위젯■  =====================>

          bottomNavigationBar: Container(

            // 03. bottomNavigationBar 위젯■  =====================>

            alignment: Alignment.center,

            width: myBanner.size.width.toDouble(),

            height: myBanner.size.height.toDouble(),

            child: AdWidget(ad: myBanner),

          ), // 03. bottomNavigationBar 위젯■  =====================>

        );

      },

    );

  }

}


// 메모 생성 및 수정 페이지

class DetailPage extends StatelessWidget {

  DetailPage({super.key, required this.index});


  final int index;


  TextEditingController contentController = TextEditingController();


  @override

  Widget build(BuildContext context) {

    debugPrint("■ [/DetailPage.C] ==> [T_01] [02. 상세 화면 Start]");


    MemoService memoService = context.read<MemoService>();

    Memo memo = memoService.memoList[index];


    contentController.text = memo.content;


    return Scaffold(

      appBar: AppBar(

        // 01. appBar 위젯■  =====================>

        actions: [

          IconButton(

            onPressed: () {

              // 삭제 버튼 클릭시

              showDeleteDialog(context, memoService);

            },

            icon: Icon(Icons.delete),

          )

        ],

      ), // 01. appBar 위젯■  =====================>

      body: Padding(

        // 02. body 위젯■ =====================>

        padding: const EdgeInsets.all(16),

        child: TextField(

          controller: contentController,

          decoration: InputDecoration(

            hintText: "메모를 입력하세요",

            border: InputBorder.none,

          ),

          autofocus: true,

          maxLines: null,

          expands: true,

          keyboardType: TextInputType.multiline,

          onChanged: (value) {

            // 텍스트필드 안의 값이 변할 때

            memoService.updateMemo(index: index, content: value);

          },

        ),

      ), // 02. body 위젯■ =====================>

    );

  }


  void showDeleteDialog(BuildContext context, MemoService memoService) {

    showDialog(

      context: context,

      builder: (context) {

        return AlertDialog(

          title: Text("정말로 삭제하시겠습니까?"),

          actions: [

            // 취소 버튼

            TextButton(

              onPressed: () {

                Navigator.pop(context);

              },

              child: Text("취소"),

            ),

            // 확인 버튼

            TextButton(

              onPressed: () {

                memoService.deleteMemo(index: index);

                Navigator.pop(context); // 팝업 닫기

                Navigator.pop(context); // HomePage 로 가기

              },

              child: Text(

                "확인",

                style: TextStyle(color: Colors.pink),

              ),

            ),

          ],

        );

      },

    );

  }

}


오류 발생 시, 작성한 코드 전체와 에러 메시지를 첨부해 주세요.

Tip 1) </> 아이콘을 눌러 코드박스를 만들어 보세요.

Tip 2) Ctrl+A(맥의 경우 Command+A) 단축키로 코드를 한 번에 선택할 수 있어요!


import 'dart:convert';


import 'package:flutter/material.dart';


import 'main.dart';


// Memo 데이터의 형식을 정해줍니다. 추후 isPinned, updatedAt 등의 정보도 저장할 수 있습니다.

class Memo {

  Memo({

    required this.content,

  });


  String content;


  Map toJson() {

    return {'content': content};

  }


  factory Memo.fromJson(json) {

    return Memo(content: json['content']);

  }

}


// Memo 데이터는 모두 여기서 관리

class MemoService extends ChangeNotifier {

  MemoService() {

    loadMemoList();

  }


  List<Memo> memoList = [

    Memo(content: '장보기 목록: 사과, 양파'), // 더미(dummy) 데이터

    Memo(content: '새 메모'), // 더미(dummy) 데이터

  ];


  createMemo({required String content}) {

    Memo memo = Memo(content: content);

    memoList.add(memo);

    notifyListeners(); // Consumer<MemoService>의 builder 부분을 호출해서 화면 새로고침

    saveMemoList();

  }


  updateMemo({required int index, required String content}) {

    Memo memo = memoList[index];

    memo.content = content;

    notifyListeners();

    saveMemoList();

  }


  deleteMemo({required int index}) {

    memoList.removeAt(index);

    notifyListeners();

    saveMemoList();

  }


  saveMemoList() {

    List memoJsonList = memoList.map((memo) => memo.toJson()).toList();

    // [{"content": "1"}, {"content": "2"}]


    String jsonString = jsonEncode(memoJsonList);

    // '[{"content": "1"}, {"content": "2"}]'


    prefs.setString('memoList', jsonString);

  }


  loadMemoList() {

    String? jsonString = prefs.getString('memoList');

    // '[{"content": "1"}, {"content": "2"}]'


    if (jsonString == null) return; // null 이면 로드하지 않음


    List memoJsonList = jsonDecode(jsonString);

    // [{"content": "1"}, {"content": "2"}]


    memoList = memoJsonList.map((json) => Memo.fromJson(json)).toList();

  }

}



취소
 공유
취소
댓글 0
댓글 알림
나의얼굴