เวอร์ชัน Android Min SDK เทียบกับเวอร์ชัน SDK เป้าหมาย


442

เมื่อพูดถึงการพัฒนาแอพพลิเคชั่นสำหรับ Android แล้วเวอร์ชั่น Min และ Target SDK แตกต่างกันอย่างไร? Eclipse จะไม่ให้ฉันสร้างโครงการใหม่ยกเว้นรุ่น Min และ Target เหมือนกัน!


1
จากสิ่งที่ฉันกำลังอ่านดูเหมือนว่า Target SDK version จะไม่มีผลต่อการรวบรวมแอปพลิเคชันของคุณ มีเพียงเพื่อแจ้งให้อุปกรณ์ทราบว่าแอปพลิเคชันทำงานอยู่โดยไม่จำเป็นต้องเปิดใช้งานคุณสมบัติความเข้ากันได้พิเศษใด ๆ เพื่อให้แอปพลิเคชันของคุณทำงานได้อย่างถูกต้อง ถูกต้องหรือไม่ ดูเหมือนว่าฉันจะไม่ทราบว่าเวอร์ชั่น SDK เป้าหมายของคุณคืออะไรจนกระทั่งหลังจากที่คุณรวบรวมและทำการทดสอบจำนวนมาก ทำไมคอมไพเลอร์ไม่สามารถดูรหัสของคุณและเข้าใจว่าแพลตฟอร์มใดที่แอปพลิเคชันของคุณเข้ากันได้ด้วยตัวเอง
Michael Novello

5
ผู้แสดงความคิดเห็นด้านบนมีความเข้าใจผิดว่าเพราะเหตุใดจึงใช้คุณลักษณะ targetSDK ดูคำตอบของฉันด้านล่างสำหรับรายละเอียดเพิ่มเติม
Steve Haley

157
คำตอบที่ยอมรับไม่ถูกต้อง โปรดอ่านคำตอบของ Steve H.
tylerl

3
@tylerl แต่มันไม่ถูกต้อง แต่มันอ้างถึงเอกสาร Google Android ฉันยังไม่ได้เพิ่มอะไรเลย
Vikas Patidar

3
คำตอบของคาร์ลนั้นละเอียดและแม่นยำที่สุดในความคิดของฉัน
Ilya Kogan

คำตอบ:


136

หุ่นยนต์: minSdkVersion

จำนวนเต็มที่กำหนดระดับ API ขั้นต่ำที่จำเป็นสำหรับแอปพลิเคชันเพื่อเรียกใช้ ระบบ Android จะป้องกันไม่ให้ผู้ใช้ติดตั้งแอปพลิเคชันหากระดับ API ของระบบต่ำกว่าค่าที่ระบุในแอตทริบิวต์นี้ คุณควรประกาศคุณลักษณะนี้เสมอ

หุ่นยนต์: targetSdkVersion

จำนวนเต็มที่กำหนดระดับ API ที่แอปพลิเคชันกำหนดเป้าหมาย

ด้วยชุดคุณลักษณะนี้แอปพลิเคชันแจ้งว่าสามารถทำงานกับเวอร์ชันเก่า (จนถึง minSdkVersion) แต่ได้รับการทดสอบอย่างชัดเจนว่าสามารถทำงานกับเวอร์ชันที่ระบุที่นี่ การระบุเวอร์ชันเป้าหมายนี้อนุญาตให้แพลตฟอร์มปิดใช้งานการตั้งค่าความเข้ากันได้ที่ไม่จำเป็นสำหรับเวอร์ชันเป้าหมาย (ซึ่งอาจเปิดใช้เพื่อรักษาความเข้ากันได้ไปข้างหน้า) หรือเปิดใช้งานฟีเจอร์ใหม่ที่ไม่สามารถใช้ได้กับแอปพลิเคชันรุ่นเก่า นี่ไม่ได้หมายความว่าคุณสามารถตั้งโปรแกรมคุณสมบัติที่แตกต่างกันสำหรับเวอร์ชั่นต่าง ๆ ของแพลตฟอร์ม - เพียงแจ้งแพลตฟอร์มที่คุณทดสอบกับเวอร์ชันเป้าหมายและแพลตฟอร์มไม่ควรทำงานพิเศษใด ๆ เพื่อรักษาความเข้ากันได้กับเวอร์ชันเป้าหมาย

สำหรับข้อมูลเพิ่มเติมอ้างอิง URL นี้:

http://developer.android.com/guide/topics/manifest/uses-sdk-element.html


โดยขนาดใหญ่คุณจะตั้งค่าทั้งสองให้เหมือนกัน มันอาจเป็นสถานการณ์ที่ผิดปกติที่พวกเขาจะตั้งค่าต่างกัน
jjb

66
เกี่ยวกับความคิดเห็นของ jjb: ฉันไม่เห็นด้วย มีเหตุผลที่ดีมากมายว่าทำไมคุณถึงมี minSDK และ targetSDK ที่แตกต่างกัน ดูคำตอบของฉันสำหรับรายละเอียดเพิ่มเติม
Steve Haley

871

ความคิดเห็นที่โพสต์โดย OP ถึงคำถาม (โดยทั่วไประบุว่าเป้าหมาย SDK ไม่ส่งผลกระทบต่อการรวบรวมแอป) นั้นผิดทั้งหมด! ขออภัยที่ต้องทื่อ

กล่าวโดยย่อนี่คือจุดประสงค์ในการประกาศเป้าหมาย SDK ที่แตกต่างจาก minSDK: หมายความว่าคุณกำลังใช้คุณสมบัติจาก SDK ระดับสูงกว่าขั้นต่ำของคุณ แต่คุณได้รับรองความเข้ากันได้ย้อนหลังมั่นใจหลังเข้ากันได้ลองจินตนาการว่าคุณต้องการใช้คุณสมบัติที่เพิ่งเปิดตัว แต่ไม่สำคัญกับแอปพลิเคชันของคุณ จากนั้นคุณจะตั้งเป้าหมาย SDK เป็นเวอร์ชันที่มีการเปิดตัวฟีเจอร์ใหม่นี้และต่ำสุดไปจนถึงสิ่งที่ต่ำกว่า

ในการยกตัวอย่างสมมติว่าคุณกำลังเขียนแอพที่ใช้การตรวจจับท่าทางอย่างละเอียด อย่างไรก็ตามทุกคำสั่งที่จดจำได้ด้วยท่าทางสามารถทำได้ด้วยปุ่มหรือจากเมนู ในกรณีนี้ท่าทางเป็น 'พิเศษที่ยอดเยี่ยม' แต่ไม่จำเป็น ดังนั้นคุณจะตั้งค่า sdk เป้าหมายเป็น 7 ("Eclair" เมื่อเปิดใช้งานห้องสมุด GestureDetection) และขั้นต่ำ SDK เป็นระดับ 3 ("Cupcake") เพื่อให้แม้แต่คนที่มีโทรศัพท์เก่าจริงๆก็สามารถใช้แอปของคุณได้ สิ่งที่คุณต้องทำคือตรวจสอบให้แน่ใจว่าแอปของคุณตรวจสอบเวอร์ชันของ Android ที่ใช้งานอยู่ก่อนที่จะพยายามใช้ไลบรารีท่าทางสัมผัสเพื่อหลีกเลี่ยงการพยายามใช้งานหากไม่มีอยู่ (เป็นที่ยอมรับว่าเป็นตัวอย่างที่ล้าสมัยเนื่องจากแทบจะทุกคนยังมีโทรศัพท์ v1.5 แต่มีเวลาในการรักษาความเข้ากันได้กับ v1

หากต้องการยกตัวอย่างอื่นคุณสามารถใช้สิ่งนี้หากคุณต้องการใช้คุณสมบัติจาก Gingerbread หรือ Honeycomb บางคนจะได้รับการอัปเดตในไม่ช้า แต่คนอื่น ๆ โดยเฉพาะกับฮาร์ดแวร์รุ่นเก่าอาจติดอยู่กับ Eclair จนกว่าพวกเขาจะซื้ออุปกรณ์ใหม่ นี่จะช่วยให้คุณใช้คุณสมบัติใหม่ ๆ ที่น่าสนใจ แต่ไม่รวมส่วนหนึ่งของตลาดที่เป็นไปได้

มีบทความที่ดีมากจากบล็อกของนักพัฒนา Androidเกี่ยวกับวิธีการใช้คุณสมบัตินี้และโดยเฉพาะอย่างยิ่งวิธีการออกแบบ "ตรวจสอบคุณสมบัติที่มีอยู่ก่อนที่จะใช้มัน" รหัสฉันกล่าวถึงข้างต้น

ถึง OP: ฉันได้เขียนสิ่งนี้เพื่อประโยชน์ของใครก็ตามที่บังเอิญสะดุดกับคำถามนี้ในอนาคตเพราะฉันรู้ว่าคำถามของคุณถูกถามมานานแล้ว


2
คุณช่วยอธิบายได้อย่างแม่นยำว่าเป้าหมาย SDKversion มีผลต่อการรวบรวมแอพอย่างไร เนื่องจากเวอร์ชันการคอมไพล์เป็นอีกการกำหนดค่าอื่นที่คุณต้องตั้งค่า ขอบคุณล่วงหน้า
hnviet

9
ฉันคิดว่า Steve สับสนระหว่างรายการคุณสมบัติ xml ของandroid android: targetSdkVersion (ซึ่งไม่มีการพูดจริง) และระหว่างคุณสมบัติเป้าหมายที่อยู่ในไฟล์ project.properties ที่แสดงถึงสิ่งที่ควรจะรวบรวมรหัส ฉันจะพูดอีกครั้ง xml attr targetSdkVersion ไม่มีความหมายที่แท้จริง !!!
AlikElzin-kilaka

3
@ kilaka ครึ่งความคิดเห็นของคุณถูกต้อง แต่อีกครึ่งหนึ่งนั้นผิด ฉันสมมติว่ามีคนใช้ค่าเดียวกันใน XML และ project.properties (สามารถเข้าถึงได้ผ่านคุณสมบัติคลิกขวา> ใน Eclipse) ดังนั้นคุณจึงควรชี้ให้เห็นว่าพวกเขาเก็บไว้ในที่ต่าง ๆ อย่างไรก็ตาม Android Market แน่นอนว่าจะคำนึงถึงคุณค่าที่คุณใส่ในแอตทริบิวต์ xml targetSdkVersion ตัวอย่างเช่นจะใช้เมื่อพิจารณาว่าคุณควรมี ActionBar หรือเมนูความเข้ากันได้สำหรับ Honeycomb และแอปพลิเคชันด้านบน
Steve Haley

2
@Nate ฉันไม่สามารถบอกได้ว่า 'convoluted code' ที่ทำงานช้าลงแค่ไหน แต่ฉันคิดว่าการแยกและใช้ APK หลาย ๆ ตัวนั้นแย่ลงในแง่ของความซับซ้อนของรหัส ตอนนี้คุณต้องจำไว้ว่าให้แสดงความคิดเห็นเข้า / ออกหรือรวมสาขาต่าง ๆ ในการควบคุมแหล่งที่มาของคุณก่อนที่คุณจะทำการส่งออกแต่ละครั้ง เมื่อการประชุม Android เมื่อเดือนตุลาคมที่ผ่านมาพวกเขากล่าวว่าพวกเขาแนะนำระบบ APK หลายระบบเป็นสัมปทาน แต่ก็มีความสุขที่มีคนเพียงไม่กี่คนที่ใช้มัน
Steve Haley

2
แต่การจัดการหลายรุ่นเป็นสิ่งที่ระบบการควบคุมเวอร์ชันทำขึ้น เป็นสิ่งที่นักพัฒนาคุ้นเคย (ซอฟต์แวร์มือถือส่วนใหญ่หรือไม่ออกรุ่นที่แตกต่างกันเล็กน้อยสำหรับแพลตฟอร์มที่แตกต่างกัน) "ฟีเจอร์" ของ Android นี้ไม่ได้ลดความซับซ้อน มันเป็นเพียงการผลักดันมันไปยังแอปพลิเคชั่นที่กำลังทำงานอยู่และเป็นหลักฐานโดยเธรดนี้ซึ่งสร้างความสับสน แน่นอนว่า Google จะมีความสุขที่มีคนไม่กี่คนที่ใช้มัน ... ที่ช่วยให้พวกเขาพูดว่า "ดูสิเราถูกต้องสำหรับการละเลยนี้ตั้งแต่แรก" นอกจากนี้บางคนไม่ใช้เพราะยังไม่รู้ว่ามีอยู่จริง
เนท

97

เมื่อคุณตั้งค่า targetSdkVersion = "xx" คุณรับรองว่าแอปของคุณทำงานได้อย่างถูกต้อง (เช่นผ่านการทดสอบอย่างละเอียดและประสบความสำเร็จ) ที่ระดับ API xx

เวอร์ชันของ Android ที่ใช้งานในระดับ API ด้านบน xx จะใช้รหัสความเข้ากันได้โดยอัตโนมัติเพื่อสนับสนุนคุณสมบัติใด ๆ ที่คุณอาจต้องใช้ที่มีอยู่ก่อนหน้าหรือในระดับ API xx แต่ตอนนี้ล้าสมัยในระดับที่สูงขึ้นของรุ่น Android

ตรงกันข้ามถ้าคุณกำลังใช้คุณลักษณะใด ๆ ที่กลายเป็นสิ่งล้าสมัยที่หรือก่อนที่จะ xx ระดับรหัสทำงานร่วมกันจะไม่ถูกนำไปใช้โดยอัตโนมัติโดยระบบปฏิบัติการรุ่นที่อยู่ในระดับสูงกว่า API (ที่ไม่รวมถึงคุณสมบัติเหล่านั้น) เพื่อสนับสนุนการใช้งานเหล่านั้น ในสถานการณ์นั้นรหัสของคุณจะต้องมีกรณีพิเศษที่ทดสอบระดับ API และหากตรวจพบระดับ OS สูงกว่าที่ไม่มีคุณสมบัติ API ที่กำหนดอีกต่อไปรหัสของคุณต้องใช้คุณสมบัติทางเลือกที่มีอยู่ในระบบปฏิบัติการที่รันอยู่ ระดับ API

หากล้มเหลวในการทำเช่นนั้นคุณสมบัติของอินเตอร์เฟสบางอย่างอาจไม่ปรากฏขึ้นซึ่งจะทำให้เกิดเหตุการณ์ภายในรหัสของคุณและคุณอาจพลาดคุณลักษณะสำคัญของอินเตอร์เฟสที่ผู้ใช้จำเป็นต้องเรียกใช้เหตุการณ์เหล่านั้นและเข้าถึงฟังก์ชันการทำงานของพวกเขา ตัวอย่างด้านล่าง)

ตามที่ระบุไว้ในคำตอบอื่น ๆ คุณอาจตั้ง targetSdkVersion สูงกว่า minSdkVersion หากคุณต้องการใช้คุณสมบัติ API บางอย่างที่กำหนดไว้ในระดับ API ที่สูงกว่า minSdkVersion ของคุณและมีขั้นตอนเพื่อให้แน่ใจว่ารหัสของคุณสามารถตรวจจับและจัดการขาดคุณสมบัติเหล่านั้น ระดับที่ต่ำกว่า targetSdkVersion

เพื่อเตือนผู้พัฒนาให้ทำการทดสอบระดับ API ขั้นต่ำที่จำเป็นต้องใช้ในการรวบรวมคอมไพเลอร์จะออกข้อผิดพลาด (ไม่ใช่แค่คำเตือน) หากรหัสประกอบด้วยการเรียกไปยังวิธีการใด ๆ ที่กำหนดไว้ในระดับ API ในภายหลังกว่า minSdkVersion แม้ว่า targetSdkVersion จะสูงกว่าหรือเท่ากับระดับ API ซึ่งวิธีการนั้นถูกทำให้พร้อมใช้งานเป็นครั้งแรก ในการลบข้อผิดพลาดนี้คอมไพเลอร์คำสั่ง

@TargetApi(nn)

บอกคอมไพเลอร์ว่าโค้ดที่อยู่ในขอบเขตของคำสั่งนั้น (ซึ่งจะนำหน้าเมธอดหรือคลาส) ถูกเขียนขึ้นเพื่อทดสอบระดับ API อย่างน้อย nn ก่อนที่จะเรียกใช้เมธอดใด ๆ ที่ขึ้นอยู่กับระดับ API นั้นอย่างน้อย . ตัวอย่างเช่นรหัสต่อไปนี้กำหนดวิธีการที่สามารถเรียกใช้จากรหัสภายในแอปที่มี minSdkVersion น้อยกว่า 11 และ targetSdkVersion เป็น 11 หรือสูงกว่า:

@TargetApi(11)
    public void refreshActionBarIfApi11OrHigher() {
      //If the API is 11 or higher, set up the actionBar and display it
      if(Build.VERSION.SDK_INT >= 11) {
        //ActionBar only exists at API level 11 or higher
        ActionBar actionBar = getActionBar();

        //This should cause onPrepareOptionsMenu() to be called.
        // In versions of the API prior to 11, this only occurred when the user pressed 
        // the dedicated menu button, but at level 11 and above, the action bar is 
        // typically displayed continuously and so you will need to call this
        // each time the options on your menu change.
        invalidateOptionsMenu();

        //Show the bar
        actionBar.show();
    }
}

คุณอาจยังต้องการที่จะประกาศ targetSdkVersion สูงขึ้นหากคุณได้รับการทดสอบในระดับที่สูงขึ้นและทุกอย่างทำงานแม้ว่าคุณไม่ได้ใช้คุณสมบัติใด ๆ จากระดับที่สูงกว่า API minSdkVersion ของคุณ นี่เป็นเพียงเพื่อหลีกเลี่ยงค่าใช้จ่ายในการเข้าถึงรหัสความเข้ากันได้ที่มีวัตถุประสงค์เพื่อปรับเปลี่ยนจากระดับเป้าหมายลงไปจนถึงระดับขั้นต่ำเนื่องจากคุณจะได้รับการยืนยัน (ผ่านการทดสอบ) ว่าไม่จำเป็นต้องปรับตัวดังกล่าว

ตัวอย่างของคุณสมบัติ UI ที่ขึ้นอยู่กับ targetSdkVersion ที่ประกาศไว้คือปุ่มเมนูสามแนวตั้งที่ปรากฏบนแถบสถานะของแอพที่มี targetSdkVersion น้อยกว่า 11 เมื่อแอปเหล่านั้นทำงานภายใต้ API 11 และสูงกว่า หากแอปของคุณมี targetSdkVersion เป็น 10 หรือต่ำกว่าจะถือว่าส่วนต่อประสานของแอพของคุณขึ้นอยู่กับปุ่มเมนูเฉพาะและดังนั้นปุ่มสามจุดจะปรากฏขึ้นแทนฮาร์ดแวร์เฉพาะรุ่นก่อนหน้านี้และ / หรือบนหน้าจอรุ่น ของปุ่มนั้น (เช่นตามที่เห็นใน Gingerbread) เมื่อระบบปฏิบัติการมีระดับ API ที่สูงขึ้นซึ่งปุ่มเมนูเฉพาะบนอุปกรณ์จะไม่ถูกสันนิษฐานอีกต่อไป อย่างไรก็ตามหากคุณตั้งค่า targetSdkVersion ของแอปเป็น 11 หรือสูงกว่าจะถือว่าคุณได้ใช้ประโยชน์จากคุณสมบัติที่แนะนำในระดับนั้นแทนที่ปุ่มเมนูเฉพาะ (e. g., แถบการกระทำ) หรือคุณไม่จำเป็นต้องมีปุ่มเมนูระบบ ดังนั้นปุ่ม "ความเข้ากันได้" สามปุ่มแนวตั้งจึงหายไป ในกรณีนั้นหากผู้ใช้ไม่พบปุ่มเมนูเธอจะไม่สามารถกดปุ่มได้และนั่นหมายความว่าการแทนที่ onCreateOptionsMenu (เมนู) ของกิจกรรมของคุณอาจไม่เคยถูกเรียกอีกต่อไปซึ่งหมายความว่า ส่วนสำคัญของการทำงานของแอพของคุณอาจถูกตัดออกจากส่วนต่อประสานผู้ใช้ แน่นอนว่าคุณได้ติดตั้ง Action Bar หรือวิธีการทางเลือกอื่น ๆ เพื่อให้ผู้ใช้สามารถเข้าถึงคุณสมบัติเหล่านี้ได้ ไม่พบปุ่มเมนูเธอไม่สามารถกดได้และในทางกลับกันหมายความว่าการแทนที่ onCreateOptionsMenu (เมนู) ของกิจกรรมของคุณอาจไม่เคยถูกเรียกใช้อีกต่อไปซึ่งหมายความว่าส่วนสำคัญของการทำงานของแอพของคุณอาจเป็น ปราศจากส่วนต่อประสานกับผู้ใช้ แน่นอนว่าคุณได้ติดตั้ง Action Bar หรือวิธีการทางเลือกอื่น ๆ เพื่อให้ผู้ใช้สามารถเข้าถึงคุณสมบัติเหล่านี้ได้ ไม่พบปุ่มเมนูเธอไม่สามารถกดได้และในทางกลับกันหมายความว่าการแทนที่ onCreateOptionsMenu (เมนู) ของกิจกรรมของคุณอาจไม่เคยถูกเรียกใช้อีกต่อไปซึ่งหมายความว่าส่วนสำคัญของการทำงานของแอพของคุณอาจเป็น ปราศจากส่วนต่อประสานกับผู้ใช้ แน่นอนว่าคุณได้ติดตั้ง Action Bar หรือวิธีการทางเลือกอื่น ๆ เพื่อให้ผู้ใช้สามารถเข้าถึงคุณสมบัติเหล่านี้ได้

ตรงกันข้าม minSdkVersion ระบุความต้องการว่าระบบปฏิบัติการเวอร์ชันของอุปกรณ์มีระดับ API อย่างน้อยนั้นเพื่อเรียกใช้แอปของคุณ สิ่งนี้มีผลกับอุปกรณ์ใดบ้างที่สามารถเห็นและดาวน์โหลดแอพของคุณเมื่ออยู่ในแอพสโตร์ของ Google Play (และอาจเป็นแอพสโตร์อื่น ๆ เช่นกัน) เป็นวิธีที่ระบุว่าแอปของคุณอาศัยฟีเจอร์ OS (API หรืออื่น ๆ ) ที่สร้างขึ้นในระดับนั้นและไม่มีวิธีที่ยอมรับได้ในการจัดการกับการขาดคุณสมบัติเหล่านั้น

ตัวอย่างของการใช้ minSdkVersion เพื่อให้แน่ใจว่ามีคุณสมบัติที่ไม่เกี่ยวข้องกับ API คือการตั้งค่า minSdkVersion เป็น 8 เพื่อให้แน่ใจว่าแอปของคุณจะทำงานเฉพาะในล่าม Dalvik รุ่น JIT (ตั้งแต่ JIT ถูกนำมาใช้ ไปยังตัวแปล Android ที่ระดับ API 8) เนื่องจากประสิทธิภาพสำหรับล่ามที่เปิดใช้งาน JIT อาจสูงถึงห้าเท่าของคุณสมบัติที่ขาดหายไปหากแอปของคุณใช้งานโปรเซสเซอร์อย่างหนักคุณอาจต้องใช้ API ระดับ 8 ขึ้นไปเพื่อประสิทธิภาพที่เพียงพอ


ขอบคุณสำหรับคำแนะนำในการใช้ TargetApi directive
samir105

@Carl หมายความว่าฉันสามารถตั้งค่า targetSdkVersion เป็นรุ่นใด ๆ ที่สูงกว่า minSdkVersion ของฉัน (โดยเฉพาะอย่างยิ่งที่จะได้รับการปรับปรุง UI เหล่านั้น) โดยไม่จำเป็นต้องทำการทดสอบใด ๆ ( ต่อครั้ง ) ตราบใดที่ฉัน จำกัด codebase ของฉัน ?
Damilola Olowookere

Olowookere Emmanuel: ถ้าฉันเข้าใจคุณอย่างถูกต้องแล้วไม่มันไม่ได้หมายความว่า ตามคำตอบของฉัน "ถ้าคุณใช้คุณสมบัติใด ๆ ที่ล้าสมัยในระดับ xx ก่อนหน้านี้รหัสความเข้ากันได้จะไม่ถูกนำไปใช้โดยอัตโนมัติในเวอร์ชั่น OS ที่ระดับ API ที่สูงขึ้น" ดังนั้นหากรหัสของคุณใช้คุณลักษณะที่มีให้ที่พูดระดับ API 8 และคุณลักษณะนั้นล้าสมัยที่ระดับ 10 จากนั้นถ้าคุณเพิ่ม targetSdkVersion ของคุณเป็นอะไรก็ตามที่สูงกว่า 10 จะไม่มีรหัสความเข้ากันได้ที่สามารถปรับการใช้งานของ คุณลักษณะนั้นไปสู่ระดับระบบปฏิบัติการใหม่
คาร์ล

(ต่อเนื่อง): ในขณะที่ถ้าคุณปล่อยให้ targetSdkVersion ของคุณอยู่ที่ระดับ 8 ในขณะที่คุณจะไม่สามารถใช้คุณสมบัติที่แนะนำในระดับที่สูงกว่าจะมีการใช้รหัสความเข้ากันได้เพื่อให้การใช้คุณสมบัติระดับ 8 ทำงานเมื่อทำงาน ระดับ OS ที่สูงขึ้น
คาร์ล

(ดำเนินการต่อ): ลองคิดแบบนี้: สมมติว่าคุณเขียนโค้ดบางอย่างเมื่อระดับ Android สูงสุดที่มีอยู่คือ 8 และคุณตั้ง targetSdkVersion เป็น 8 (เพราะเป็นระดับสูงสุดในเวลานั้น) ตอนนี้ Android รุ่นใหม่ออกมาแล้วและฟีเจอร์ระดับ 8 บางส่วนที่คุณใช้ไม่สามารถใช้งานได้ ผู้ใช้ที่ยังมี APK เก่าของคุณไม่ควรพบข้อผิดพลาด ดังนั้นเพื่อให้แน่ใจว่าไม่มีรหัสความเข้ากันได้จะถูกนำไปใช้โดยอัตโนมัติเพื่อปรับการเรียก API เก่าของคุณเพื่อทำสิ่งที่สมเหตุสมผลเมื่อมีการเรียกใช้ในขณะที่ผู้ใช้เรียกใช้ระบบปฏิบัติการเวอร์ชันใหม่กว่า
Carl

50

แนวคิดสามารถนำส่งตัวอย่างที่ดีขึ้นได้เสมอแนวคิดที่สามารถส่งตัวอย่างที่ดีขึ้นด้วยเสมอฉันมีปัญหาในการทำความเข้าใจแนวคิดเหล่านี้จนกว่าฉันจะขุดลงในซอร์สโค้ดของ Android เฟรมเวิร์กและทำการทดลองบางอย่างแม้หลังจากอ่านเอกสารทั้งหมดในไซต์นักพัฒนาซอฟต์แวร์ Android และเธรดสแต็คโอเวอร์โฟลว์ที่เกี่ยวข้อง ฉันจะแบ่งปันสองตัวอย่างที่ช่วยให้ฉันเข้าใจแนวคิดเหล่านี้ได้อย่างสมบูรณ์

DatePickerDialogจะมีลักษณะที่แตกต่างกันขึ้นอยู่กับระดับที่คุณใส่ใน targetSDKversion ไฟล์ AndroidManifest.xml ของ ( <uses-sdk android:targetSdkVersion="INTEGER_VALUE"/>) หากคุณตั้งค่าเป็น 10 หรือต่ำกว่า DatePickerDialog ของคุณจะดูเหมือนซ้าย ในทางตรงกันข้ามถ้าคุณตั้งค่า 11 หรือสูงกว่า DatePickerDialog จะมีลักษณะเช่นขวาด้วยรหัสเดียวกันมาก

DatePickerDialog ดูด้วย targetSDKversion 10 หรือต่ำกว่า DatePickerDialog มองหาเป้าหมาย SDKversion 11 ขึ้นไป

รหัสที่ฉันใช้ในการสร้างตัวอย่างนี้ง่ายมาก MainActivity.javaหน้าตา:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void onClickButton(View v) {
        DatePickerDialog d = new DatePickerDialog(this, null, 2014, 5, 4);
        d.show();       
    }
}

และactivity_main.xmlรูปลักษณ์:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="onClickButton"
    android:text="Button" />
</RelativeLayout>


แค่นั้นแหละ. นั่นเป็นรหัสจริงๆที่ฉันต้องทดสอบ

และการเปลี่ยนแปลงนี้ในรูปลักษณ์ใสเมื่อคุณเห็นรหัสที่มา Android กรอบ มันไปเช่น:

public DatePickerDialog(Context context,
    OnDateSetListener callBack,
    int year,
    int monthOfYear,
    int dayOfMonth,
    boolean yearOptional) {
        this(context, context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB
                ? com.android.internal.R.style.Theme_Holo_Light_Dialog_Alert
                : com.android.internal.R.style.Theme_Dialog_Alert,
        callBack, year, monthOfYear, dayOfMonth, yearOptional);
}

อย่างที่คุณเห็นเฟรมเวิร์กรับเป้าหมายปัจจุบัน SDKversion และกำหนดธีมที่แตกต่าง ตัวอย่างรหัสนี้ ( getApplicationInfo().targetSdkVersion >= SOME_VERSION) สามารถพบได้ที่นี่และในกรอบของ Android

อีกตัวอย่างหนึ่งคือเกี่ยวกับคลาสWebView เมธอดสาธารณะของคลาส Webview ควรถูกเรียกใช้บนเธรดหลักและหากไม่ใช่ระบบรันไทม์จะพ่น a RuntimeExceptionเมื่อคุณตั้งค่าเป้าหมาย SDKversion 18 หรือสูงกว่า ลักษณะการทำงานนี้สามารถจัดส่งได้อย่างชัดเจนด้วยรหัสแหล่งที่มาของ มันแค่เขียนแบบนั้น

sEnforceThreadChecking = context.getApplicationInfo().targetSdkVersion >=
            Build.VERSION_CODES.JELLY_BEAN_MR2;

if (sEnforceThreadChecking) {
    throw new RuntimeException(throwable);
}


เอกสาร Androidกล่าวว่า " ในขณะที่ Android วิวัฒนาการพร้อมกับเวอร์ชั่นใหม่แต่ละพฤติกรรมและพฤติกรรมที่ปรากฏอาจมีการเปลี่ยนแปลง ." ดังนั้นเราจึงดูพฤติกรรมและการเปลี่ยนแปลงลักษณะที่ปรากฏและวิธีการเปลี่ยนแปลงนั้นสำเร็จได้อย่างไร

โดยสรุปเอกสาร Android ระบุว่า " คุณลักษณะนี้ (targetSdkVersion) แจ้งให้ระบบทราบว่าคุณได้ทดสอบกับเวอร์ชันเป้าหมายแล้วและระบบไม่ควรเปิดใช้งานพฤติกรรมการทำงานร่วมกันเพื่อรักษาความเข้ากันได้ของแอปของคุณกับเวอร์ชันเป้าหมาย " ชัดเจนมากในกรณีของ WebView ไม่เป็นไรจนกว่าจะปล่อย JELLY_BEAN_MR2 เพื่อเรียกวิธีสาธารณะของคลาส WebView บนเธรดหลัก มันเป็นเรื่องไร้สาระถ้ากรอบ Android พ่น RuntimeException บนอุปกรณ์ JELLY_BEAN_MR2 มันไม่ควรเปิดใช้งานพฤติกรรมที่แนะนำใหม่เพื่อผลประโยชน์ซึ่งก่อให้เกิดผลลัพธ์ที่ร้ายแรง ดังนั้นสิ่งที่เราต้องทำคือการตรวจสอบว่าทุกอย่างโอเคกับเป้าหมาย SDKversions ที่แน่นอนหรือไม่ เราได้รับประโยชน์เช่นการปรับปรุงรูปลักษณ์ด้วยการตั้งค่าเป้าหมายที่สูงขึ้น SDKversion

แก้ไข: ข้อจำกัดความรับผิดชอบ ตัวสร้าง DatePickerDialog ว่ารูปแบบที่แตกต่างกันขึ้นอยู่กับการตั้งค่า targetSDKversion ปัจจุบัน (ที่ผมแสดงให้เห็นด้านบน) ที่จริงมีการเปลี่ยนแปลงในภายหลังกระทำ อย่างไรก็ตามฉันใช้ตัวอย่างนั้นเนื่องจากตรรกะไม่ได้ถูกเปลี่ยนแปลงและข้อมูลโค้ดเหล่านั้นแสดงแนวคิดของ targetSDKversion อย่างชัดเจน


2
"เราได้รับประโยชน์เช่นการปรับปรุงรูปลักษณ์ด้วยการตั้งเป้าหมายที่สูงขึ้น SDKversion แต่มาพร้อมกับความรับผิดชอบ" หากพวกเขาพูดถึงเรื่องนี้ในเอกสารฉันจะไม่มองหามัน
pulp_fiction

@ 김준호ฉันถามคำถามสองข้อ: 1. ) ในตัวอย่าง datepicker ด้านบนหากคุณตั้ง targetSdkVersion เป็น 10 หรือต่ำกว่าและเรียกใช้แอปบนอุปกรณ์ที่ใช้ Android ล่าสุด (เช่น API 22) datepicker จะยังคงแสดงเหมือนเก่า บนภาพด้านซ้าย? 2. ) มันไม่ได้หมายความว่าผมสามารถตั้ง targetSdkVersion ไปยังเวอร์ชันที่สูงกว่า minSdkVersion ของฉัน (เช่นที่จะได้รับการปรับปรุง UI ผู้ที่ต้องการที่ datepicker กรอบจาก API ที่สูงกว่า) โดยไม่จำเป็นต้องสำหรับการทดสอบใด ๆ ( ต่อ se ) ตราบเท่าที่ฉัน จำกัด codebase ของฉัน ใช้เฉพาะ API ที่มีอยู่ใน minSdkVersion ของฉันได้อย่างไร
Damilola Olowookere

@Ologoookere 1) ใช่ เพียงแค่เรียกใช้มัน 2) คุณสามารถกำหนดเป้าหมาย SDKVersion เวอร์ชันใดก็ได้ที่คุณต้องการหากสูงกว่า minSDKVersion แต่คุณยังคงต้องทดสอบว่ามันใช้งานได้ดีกับรุ่นเป้าหมายหรือไม่ ไม่สำคัญว่าคุณจะติดอยู่กับ minSDKVersion api หรือไม่ นึกถึงตัวอย่าง DatePicker
김준호

นึกถึงกรณีที่คุณตั้งค่า min version 14 & target sdk version เป็น 16 และคุณใช้ apis เพียง 14 หรือต่ำกว่า สมมติว่าคุณใช้ TextView ที่แนะนำใน api ระดับ 1 จะเกิดอะไรขึ้น
김준호

@ 김준호ขอบคุณ แต่สำหรับคำตอบที่สองของคุณฉันสับสน หากรหัสของฉันใช้เฉพาะ API ใน minSdkVersion และฉันกำหนดเป้าหมาย SDK ที่สูงขึ้นฉันจะต้องทดสอบอะไร เมื่อคิดถึงตัวอย่างของ DatePicker แล้ว targetSdkVersion ที่สูงขึ้นจะปรับปรุงเฉพาะรูปลักษณ์ของวิดเจ็ต DatePicker และไม่มีการหยุดพักเนื่องจากฉันไม่ได้ใช้รหัสใด ๆ ใน API ที่สูงกว่า minSdkVersion ฉันต้องการ targetSdkVersion ที่สูงขึ้นเท่านั้นเพราะฉันต้องการรูปลักษณ์ใหม่ของวิดเจ็ตไม่ใช่ว่าฉันต้องการใช้คุณลักษณะใหม่ที่เปิดตัวที่ API ที่สูงกว่า
Damilola Olowookere

21

สำหรับผู้ที่ต้องการสรุป

android:minSdkVersion

เป็นรุ่นขั้นต่ำจนกระทั่งใบสมัครของคุณรองรับ หากอุปกรณ์ของคุณมีแอนดรอยด์เวอร์ชั่นต่ำกว่าแอพจะไม่ติดตั้ง

ในขณะที่

android:targetSdkVersion

เป็นระดับ API จนถึงที่แอพของคุณออกแบบมาให้ทำงาน หมายความว่าระบบโทรศัพท์ของคุณไม่จำเป็นต้องใช้พฤติกรรมการทำงานร่วมกันเพื่อรักษาความเข้ากันได้ไปข้างหน้าเพราะคุณได้ทดสอบจนถึง API นี้

แอปของคุณจะยังคงทำงานในเวอร์ชัน Android ที่สูงกว่าที่กำหนดtargetSdkVersionแต่พฤติกรรมความเข้ากันได้ของ Android จะเริ่มขึ้น

Freebie -

android:maxSdkVersion

หากเวอร์ชัน API ของอุปกรณ์ของคุณสูงกว่าแอปจะไม่ติดตั้ง กล่าวคือ นี่คือ API สูงสุดจนถึงที่คุณอนุญาตให้แอปของคุณติดตั้ง

กล่าวคือ สำหรับ MinSDK -4, maxSDK - 8, targetSDK - 8 แอพของฉันจะทำงานที่ขั้นต่ำ 1.6 แต่ฉันยังใช้คุณสมบัติที่รองรับเฉพาะใน 2.2 ซึ่งจะมองเห็นได้หากติดตั้งบนอุปกรณ์ 2.2 นอกจากนี้สำหรับ maxSDK - 8 แอพนี้จะไม่ติดตั้งบนโทรศัพท์ที่ใช้ API> 8

ในขณะที่เขียนคำตอบนี้เอกสาร Android ไม่สามารถอธิบายได้ดีนัก ตอนนี้มันอธิบายได้ดีมาก ตรวจสอบที่นี่


'เป็นรุ่นสูงสุดที่แอปของคุณได้รับคุณสมบัติ' : นี่มันผิด เป็นรุ่นขั้นต่ำที่แอพของคุณมีคุณสมบัติที่สืบทอดมา - คือเวอร์ชันแรกที่มีคุณสมบัติที่จำเป็นที่แอพของคุณใช้
RichieHH

ภาษาอังกฤษเป็นภาษาที่หากิน อ่านตัวอย่างของฉันในคำตอบ ฉันคิดว่าฉันเข้าท่าแล้ว :)
Darpan

ฉันไม่คล่องแคล่วและภาษาอังกฤษเป็นภาษาที่สนับสนุนในกลุ่มนี้ หากินหรือไม่บอกว่าเป็น "เวอร์ชั่นสูงสุดที่แอพรองรับฟีเจอร์" ไม่เพียง แต่ผิด: มันผิดทั้งหมด 180 องศา เป็นรุ่นแรกหรือรุ่นต่ำสุดที่รองรับคุณสมบัติที่ตั้งใจทั้งหมดของแอปพลิเคชันของคุณโดยไม่ต้องใช้โหมด / ไลบรารีความเข้ากันได้ทางเลือกย้อนกลับ
RichieHH

9

หากคุณได้รับข้อผิดพลาดในการรวบรวมเช่น:

<uses-sdk
            android:minSdkVersion="10"
            android:targetSdkVersion="15" />

.

private void methodThatRequiresAPI11() {
        BitmapFactory.Options options = new BitmapFactory.Options();
                options.inPreferredConfig = Config.ARGB_8888;  // API Level 1          
                options.inSampleSize = 8;    // API Level 1
                options.inBitmap = bitmap;   // **API Level 11**
        //...
    }

คุณได้รับข้อผิดพลาดในการคอมไพล์:

ฟิลด์ต้องใช้ API ระดับ 11 (ขั้นต่ำปัจจุบันคือ 10): android.graphics.BitmapFactory $ ตัวเลือก # inBitmap

ตั้งแต่รุ่น 17 ของเครื่องมือพัฒนา Android (ADT) มีหนึ่งคำอธิบายประกอบใหม่และมีประโยชน์มาก@TargetApiที่สามารถแก้ไขปัญหานี้ได้อย่างง่ายดาย เพิ่มก่อนวิธีการที่ล้อมรอบประกาศที่มีปัญหา:

@TargetApi
private void methodThatRequiresAPI11() {            
  BitmapFactory.Options options = new BitmapFactory.Options();
      options.inPreferredConfig = Config.ARGB_8888;  // API Level 1          
      options.inSampleSize = 8;    // API Level 1

      // This will avoid exception NoSuchFieldError (or NoSuchMethodError) at runtime. 
      if (Integer.valueOf(android.os.Build.VERSION.SDK) >= android.os.Build.VERSION_CODES.HONEYCOMB) {
        options.inBitmap = bitmap;   // **API Level 11**
            //...
      }
    }

ไม่มีข้อผิดพลาดในการรวบรวมในขณะนี้และมันจะทำงาน!

แก้ไข: สิ่งนี้จะส่งผลให้เกิดข้อผิดพลาดรันไทม์ในระดับ API ต่ำกว่า 11 ในวันที่ 11 หรือสูงกว่านั้นจะทำงานโดยไม่มีปัญหา ดังนั้นคุณต้องแน่ใจว่าคุณเรียกวิธีการนี้ในเส้นทางการดำเนินการที่ได้รับการปกป้องโดยการตรวจสอบรุ่น TargetApi ช่วยให้คุณสามารถรวบรวมได้ แต่คุณต้องรับความเสี่ยงด้วยตนเอง


1
ฉันสับสนเกี่ยวกับเรื่องนี้ จะเกิดอะไรขึ้นถ้าคุณรันแอปของคุณในระบบด้วย sdk 10
Fran Marzoa

มันจะออกจาก options.inBitmap และแอปจะทำงานได้ดี
NinjaCoder

1

android:minSdkVersionและ android:targetSdkVersionทั้งคู่เป็นค่าจำนวนเต็มเราต้องประกาศในไฟล์รายการหุ่นยนต์ แต่ทั้งคู่มีคุณสมบัติแตกต่างกัน

android:minSdkVersion:นี่เป็นระดับ API ขั้นต่ำที่จำเป็นในการเรียกใช้แอพ Android หากเราจะติดตั้งแอพเดียวกันในเวอร์ชั่น API ที่ต่ำกว่าข้อผิดพลาดในการแยกวิเคราะห์จะปรากฏขึ้นและแอปพลิเคชันที่ไม่รองรับปัญหาจะปรากฏขึ้น

android:targetSdkVersion:Target sdk version คือการตั้งระดับ Target API ของแอพ หากแอตทริบิวต์นี้ไม่ได้ประกาศในรายการรุ่น minSdk จะเป็นเวอร์ชัน TargetSdk ของคุณ นี่เป็นความจริงเสมอว่า "การติดตั้งแอปรองรับใน API ที่สูงกว่าทั้งหมดที่เราประกาศว่าเป็น TargetSdk เวอร์ชัน" ในการทำให้เป้าหมายมี จำกัด เราต้องประกาศ maxSdkVersion ในไฟล์รายการของเรา ...


0

หากคุณกำลังสร้างแอพที่ต้องการการอนุญาตที่เป็นอันตรายและตั้งค่าเป้าหมาย SDK เป็น 23 ขึ้นไปคุณควรระมัดระวัง หากคุณไม่ตรวจสอบการอนุญาตบนรันไทม์คุณจะได้รับ SecurityException และหากคุณใช้รหัสในบล็อกลองตัวอย่างเช่นกล้องที่เปิดอยู่อาจเป็นการยากที่จะตรวจพบข้อผิดพลาดหากคุณไม่ตรวจสอบ logcat


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.