অ্যান্ড্রয়েড প্ল্যাটফর্মে কনফিগারেশন ডেটা (যেমন, অডিও কনফিগারেশন) সংরক্ষণের জন্য অনেক XML ফাইল থাকে। এই XML ফাইলগুলোর বেশিরভাগই vendor পার্টিশনে থাকে, কিন্তু সেগুলো system পার্টিশন থেকে পড়া হয়। এক্ষেত্রে, XML ফাইলের স্কিমাটি দুটি পার্টিশনের মধ্যে ইন্টারফেস হিসেবে কাজ করে, এবং তাই স্কিমাটি অবশ্যই সুস্পষ্টভাবে নির্দিষ্ট করতে হবে এবং ব্যাকওয়ার্ড-কম্প্যাটিবল পদ্ধতিতে এর পরিবর্তন নিশ্চিত করতে হবে।
অ্যান্ড্রয়েড ১০-এর আগে, প্ল্যাটফর্মটিতে এক্সএমএল স্কিমা নির্দিষ্ট করা ও ব্যবহার বাধ্যতামূলক করার, অথবা স্কিমাতে অসঙ্গত পরিবর্তন প্রতিরোধ করার কোনো ব্যবস্থা ছিল না। অ্যান্ড্রয়েড ১০ এই ব্যবস্থাটি প্রদান করে, যার নাম কনফিগ ফাইল স্কিমা এপিআই (Config File Schema API)। এই ব্যবস্থাটি xsdc নামক একটি টুল এবং xsd_config নামক একটি বিল্ড রুল নিয়ে গঠিত।
xsdc টুলটি একটি এক্সএমএল স্কিমা ডকুমেন্ট (XSD) কম্পাইলার। এটি একটি এক্সএমএল ফাইলের স্কিমা বর্ণনা করে এমন একটি XSD ফাইল পার্স করে জাভা এবং সি++ কোড তৈরি করে। তৈরি করা কোডটি XSD স্কিমা মেনে চলা এক্সএমএল ফাইলগুলোকে পার্স করে অবজেক্টের একটি ট্রি-তে পরিণত করে, যার প্রতিটি অবজেক্ট একটি এক্সএমএল ট্যাগকে মডেল করে। এক্সএমএল অ্যাট্রিবিউটগুলোকে অবজেক্টের ফিল্ড হিসেবে মডেল করা হয়।
xsd_config বিল্ড রুলটি xsdc টুলকে বিল্ড সিস্টেমের সাথে একীভূত করে। একটি নির্দিষ্ট XSD ইনপুট ফাইলের জন্য, এই বিল্ড রুলটি জাভা এবং C++ লাইব্রেরি তৈরি করে। আপনি এই লাইব্রেরিগুলোকে সেই মডিউলগুলোর সাথে লিঙ্ক করতে পারেন, যেখানে XSD-সম্মত XML ফাইলগুলো পড়া ও ব্যবহার করা হয়। আপনি system এবং vendor পার্টিশন জুড়ে ব্যবহৃত আপনার নিজস্ব XML ফাইলগুলোর জন্যও এই বিল্ড রুলটি ব্যবহার করতে পারেন।
বিল্ড কনফিগারেশন ফাইল স্কিমা এপিআই
এই অংশে কনফিগ ফাইল স্কিমা এপিআই (Config File Schema API) তৈরি করার পদ্ধতি বর্ণনা করা হয়েছে।
Android.bp-তে xsd_config বিল্ড রুলটি কনফিগার করুন।
xsd_config বিল্ড রুলটি xsdc টুলের সাহায্যে পার্সার কোড তৈরি করে। xsd_config বিল্ড রুলের package_name প্রপার্টিটি তৈরি হওয়া জাভা কোডের প্যাকেজ নাম নির্ধারণ করে।
Android.bp তে xsd_config বিল্ড নিয়মের উদাহরণ:
xsd_config {
name: "hal_manifest",
srcs: ["hal_manifest.xsd"],
package_name: "hal.manifest",
}
ডিরেক্টরি কাঠামোর উদাহরণ:
├── Android.bp
├── api
│ ├── current.txt
│ ├── last_current.txt
│ ├── last_removed.txt
│ └── removed.txt
└── hal_manifest.xsd
বিল্ড সিস্টেম জেনারেট করা জাভা কোড ব্যবহার করে একটি এপিআই তালিকা তৈরি করে এবং তার সাথে এপিআই-টি মিলিয়ে দেখে। এই এপিআই চেকটি ড্রয়েডকোর-এ যোগ করা হয় এবং m -j তে এক্সিকিউট করা হয়।
এপিআই তালিকা ফাইল তৈরি করুন
এপিআই চেকের জন্য সোর্স কোডে এপিআই লিস্ট ফাইলগুলোর প্রয়োজন হয়।
এপিআই তালিকাভুক্ত ফাইলগুলির মধ্যে রয়েছে:
- বিল্ড করার সময় তৈরি হওয়া API ফাইলগুলোর সাথে তুলনা করে
current.txtএবংremoved.txtযাচাই করে দেখে যে API-গুলো পরিবর্তিত হয়েছে কিনা। -
last_current.txtএবংlast_removed.txtAPI ফাইলের সাথে তুলনা করে API-গুলো ব্যাকওয়ার্ড কম্প্যাটিবল কিনা তা যাচাই করে।
এপিআই তালিকা ফাইলগুলি তৈরি করতে:
- খালি তালিকা ফাইল তৈরি করুন।
-
make update-apiকমান্ডটি চালান।
জেনারেট করা পার্সার কোড ব্যবহার করুন
জেনারেট করা জাভা কোড ব্যবহার করতে, জাভা srcs প্রপার্টিতে xsd_config মডিউল নামের আগে : যোগ করুন। জেনারেট করা জাভা কোডের প্যাকেজটি package_name প্রপার্টির মতোই।
java_library {
name: "vintf_test_java",
srcs: [
"srcs/**/*.java"
":hal_manifest"
],
}
জেনারেট করা C++ কোড ব্যবহার করতে, generated_sources এবং generated_headers প্রপার্টিগুলোতে xsd_config মডিউলের নামটি যোগ করুন। এবং static_libs বা shared_libs এ libxml2 যোগ করুন, কারণ জেনারেট করা পার্সার কোডে libxml2 প্রয়োজন হয়। জেনারেট করা C++ কোডের নেমস্পেসটি package_name প্রপার্টির নেমস্পেসের সমান হয়। উদাহরণস্বরূপ, যদি xsd_config মডিউলের নাম hal.manifest হয়, তাহলে নেমস্পেসটি হবে hal::manifest ।
cc_library{
name: "vintf_test_cpp",
srcs: ["main.cpp"],
generated_sources: ["hal_manifest"],
generated_headers: ["hal_manifest"],
shared_libs: ["libxml2"],
}
পার্সারটি ব্যবহার করুন
জাভা পার্সার কোড ব্যবহার করতে, রুট এলিমেন্টের ক্লাস রিটার্ন করার জন্য XmlParser#read অথবা read{ class-name } মেথডটি ব্যবহার করুন। এই সময়েই পার্সিং সম্পন্ন হয়।
import hal.manifest.*;
…
class HalInfo {
public String name;
public String format;
public String optional;
…
}
void readHalManifestFromXml(File file) {
…
try (InputStream str = new BufferedInputStream(new FileInputStream(file))) {
Manifest manifest = XmlParser.read(str);
for (Hal hal : manifest.getHal()) {
HalInfo halinfo;
HalInfo.name = hal.getName();
HalInfo.format = hal.getFormat();
HalInfo.optional = hal.getOptional();
…
}
}
…
}
C++ পার্সার কোড ব্যবহার করার জন্য, প্রথমে হেডার ফাইলটি অন্তর্ভুক্ত করুন। হেডার ফাইলের নামটি হলো প্যাকেজের নাম, যেখানে ডট (.) চিহ্নগুলোকে আন্ডারস্কোর (_) দিয়ে প্রতিস্থাপন করতে হবে। এরপর, রুট এলিমেন্টের ক্লাস রিটার্ন করার জন্য read অথবা read{ class-name } মেথডটি ব্যবহার করুন। এই সময়েই পার্সিং সম্পন্ন হয়। রিটার্ন ভ্যালুটি হলো একটি std::optional<> ।
include "hal_manifest.h"
…
using namespace hal::manifest
struct HalInfo {
public std::string name;
public std::string format;
public std::string optional;
…
};
void readHalManifestFromXml(std::string file_name) {
…
Manifest manifest = *read(file_name.c_str());
for (Hal hal : manifest.getHal()) {
struct HalInfo halinfo;
HalInfo.name = hal.getName();
HalInfo.format = hal.getFormat();
HalInfo.optional = hal.getOptional();
…
}
…
}
পার্সারটি ব্যবহার করার জন্য প্রদত্ত সমস্ত এপিআই (API) api/current.txt ফাইলে রয়েছে। সামঞ্জস্য রক্ষার জন্য, সমস্ত এলিমেন্ট এবং অ্যাট্রিবিউটের নাম ক্যামেল কেসে (যেমন, ElementName ) রূপান্তর করা হয় এবং সংশ্লিষ্ট ভেরিয়েবল, মেথড এবং ক্লাসের নাম হিসেবে ব্যবহার করা হয়। পার্স করা রুট এলিমেন্টের ক্লাস read{ class-name } ফাংশনটি ব্যবহার করে পাওয়া যায়। যদি কেবল একটি রুট এলিমেন্ট থাকে, তাহলে ফাংশনের নাম হয় read । পার্স করা সাব-এলিমেন্ট বা অ্যাট্রিবিউটের মান get{ variable-name } ফাংশনটি ব্যবহার করে পাওয়া যায়।
পার্সার কোড তৈরি করুন
বেশিরভাগ ক্ষেত্রে, আপনার সরাসরি xsdc চালানোর প্রয়োজন নেই। এর পরিবর্তে, Android.bp-তে xsd_config বিল্ড রুল কনফিগার করার অংশে বর্ণিত xsd_config বিল্ড রুলটি ব্যবহার করুন। শুধুমাত্র সম্পূর্ণতার জন্য, এই অংশে xsdc কমান্ড লাইন ইন্টারফেসটি ব্যাখ্যা করা হয়েছে। এটি ডিবাগিংয়ের জন্য সহায়ক হতে পারে।
আপনাকে অবশ্যই xsdc টুলটিকে XSD ফাইলের পাথ এবং একটি প্যাকেজ দিতে হবে। জাভা কোডে প্যাকেজ হলো একটি প্যাকেজের নাম এবং C++ কোডে এটি একটি নেমস্পেস। তৈরি হওয়া কোডটি জাভা নাকি C হবে, তা নির্ধারণ করার অপশনগুলো হলো যথাক্রমে -j বা -c । -o অপশনটি হলো আউটপুট ডিরেক্টরির পাথ।
usage: xsdc path/to/xsd_file.xsd [-c] [-j] [-o <arg>] [-p]
-c,--cpp Generate C++ code.
-j,--java Generate Java code.
-o,--outDir <arg> Out Directory
-p,--package Package name of the generated java file. file name of
generated C++ file and header
উদাহরণ কমান্ড:
$ xsdc audio_policy_configuration.xsd -p audio.policy -j