بسم الله الرحمن الرحيم
اليوم إن شاء الله رح نتعلم درس في كيفية ارسال اشعارات لجميع من يستخدم تطبيقك بواسطة سيرفر سحابة التراسل من جوجل gcm وهذا هو الدرس الرابع لنا في التعامل مع هذا السيرفر الضخم, ولنا دروس قادمة إن شاء الله فيه.
# راجع الدروس السابقة حول gcm :
- مقدمة لاستخدام GCM ببرمجة تطبيقات الاندرويد + تجهيزها
- ارسال الاشعارات في تطبيقات اندرويد برمجياً باستخدام GCM
- ارسال الاشعارات لاجهزة متعددة GCM – Android – PHP – MySQL
هذا الدرس هو نتيجة للدروس السابقة, فقد تعديل على ما سبق, وسوف نحتاج من الدروس السابقة :
Project Number + API Server Key
# معاينة لهذا الدرس :
# المتطلبات :
– تطبيق الويب / تطبيق بلغة php بسيط ومتصل بقاعدة بيانات MySQL لتخزين معرفات الاجهزة المتصلة من ثم ارسال المعرف والرسالة إلى سيرفر سحابة جوجل GCM لأرسال الرسالة للمستخدم.
– تطبيق اندرويد / في حال قام بتشغيله المستخدم لأول مرة يقوم بتخزين معرف له و يرسل هذا المعرف لقاعدة البيانات.
# تجهيز تطبيق الويب :
كما ذكرنا سابقاً في دروس سابقة يجب أن يكون لديك مزود خدمة ( استضافة ) من أجل أن تقوم بقرائة تطبيق الويب وقاعدة البيانات.
– تنشأ مجلد خاص للـ GCM وتضع فيه الملفات التالية :
db_connect.php
db_functions.php
insertuser.php
processmessage.php
send.php
– حسب موقعك او السيرفر الذي تستخدمه لا تنسى وضع مسار insertuser.php في تطبيق الاندرويد لإضافة المستخدم لقاعدة البيانات.
– كذلك في ملف processmessage.php لا تنسى بإن تقوم بوضع API Server Key حسب الموجود لديك في مشروعك في جوجل, وهذا ما اخذناه في الدرس الأول.
عموماً بالنسبة لي وفي هذا الدرس سوف أستخدم السيرفر الداخلي الاباتشي, ووضع مجلد داخله بإسم gcm و إنشاء قاعدة بيانات بإسم andrody ووضع فيها حقلين, الاول id وهو ترتيب فقط يضاف تلقائي للاجهزة الاول, الثاني .. إلخ, أما الحقل الآخر فهو لتخزين الاي دي المسجل للمستخدم.
# تابع معي الخطوات :
فتح السيرفر وإنشاء قاعدة بيانات بإسم andrody , اضف فيها الأمر التالي لاضافة الجدول وحقوله :
CREATE TABLE IF NOT EXISTS `gcmusers` ( `id` int(11) NOT NULL AUTO_INCREMENT, `gcmregid` varchar(500) NOT NULL, PRIMARY KEY (`id`) )
والآن فتح مجلدات السيرفر www و إضافة فيها مجلد بإسم gcm ومن ثم إضافة فيه الملفات التالية :
db_connect.php
لا تنسى بإن تقوم بتغيير معلومات الاتصال بالقاعدة كما لديك في السيرفر
<?php class DB_Connect { // constructor function __construct() { } // destructor function __destruct() { // $this->close(); } // Connecting to database public function connect() { define("DB_HOST", "localhost"); define("DB_USER", "root"); // اسم المستخدم لقاعدة البيانات define("DB_PASSWORD", "13241324"); // كلمة المرور لقاعدة البيانات define("DB_DATABASE", "andrody"); // اسم قاعدة البيانات // connecting to mysql $con = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD); // selecting database mysql_select_db(DB_DATABASE); // return database handler return $con; } // Closing database connection public function close() { mysql_close(); } } ?>
db_functions.php
<?php class DB_Functions { private $db; function __construct() { include_once './db_connect.php'; // Connect to database $this->db = new DB_Connect(); $this->db->connect(); } // destructor function __destruct() { } /** * Insert new user * */ public function insertUser($gcmRegId) { // Insert user into database $result = mysql_query("INSERT INTO gcmusers (gcmregid) VALUES('$gcmRegId')"); if ($result) { return true; } else { return false; } } /** * Select all user * */ public function getAllUsers() { $result = mysql_query("select * FROM gcmusers"); return $result; } /** * Get GCMRegId * */ public function getGCMRegID($emailID){ $result = mysql_query("SELECT gcmregid FROM gcmusers WHERE id = "."'$emailID'"); return $result; } } ?>
insertuser.php
<?php include_once './db_functions.php'; //Create Object for DB_Functions clas $db = new DB_Functions(); $regId = $_POST["regId"]; $res = $db->insertUser($regId); echo "RegId ".$regId ; if ($res) { echo "GCM Reg Id bas been shared successfully with Server"; } else { echo "Error occured while sharing GCM Reg Id with Server web app"; } ?>
processmessage.php
لا تنسى بتغيير API Server Key كما لديك في مشروعك في جوجل
<?php //Generic php function to send GCM push notification function sendPushNotificationToGCM($registation_ids, $message) { //Google cloud messaging GCM-API url $url = 'https://android.googleapis.com/gcm/send'; $fields = array( 'registration_ids' => $registation_ids, 'data' => $message, ); // Update your Google Cloud Messaging API Key if (!defined('GOOGLE_API_KEY')) { define("GOOGLE_API_KEY", "API Server Key"); } $headers = array( 'Authorization: key=' . GOOGLE_API_KEY, 'Content-Type: application/json' ); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields)); $result = curl_exec($ch); if ($result === FALSE) { die('Curl failed: ' . curl_error($ch)); } curl_close($ch); return $result; } ?> <?php include_once 'db_functions.php'; $db = new DB_Functions(); $selUsers = $_POST['sendmsg']; if(empty($selUsers)) { echo("You didn't select any users."); } else { $resp = "<tr id='header'><td>GCM Response [".date("h:i:sa")."]</td></tr>"; $userCount = count($selUsers); $greetMsg = $_POST['message']; $respJson = $greetMsg; $registation_ids = array(); for($i=0; $i < $userCount; $i++) { $gcmRegId = $db->getGCMRegID($selUsers[$i]); $row = mysql_fetch_assoc($gcmRegId); //Add RegIds retrieved from DB to $registration_ids array_push($registation_ids, $row['gcmregid']); } // JSON Msg to be transmitted to selected Users $message = array("m" => $respJson); $pushsts = sendPushNotificationToGCM($registation_ids, $message); $resp = $resp."<tr><td>".$pushsts."</td></tr>"; echo "<table>".$resp."</table>"; } ?>
send.php
<html> <head><title>ارسال اشعارات للمستخدمين</title> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <style> body { font: normal medium/1.4 sans-serif; } div.greetblock, div.serverresponse { border-collapse: collapse; width: 100%; margin-left: auto; margin-right: auto; align: center; } tr > td { padding: 0.25rem; text-align: center; border: 1px solid #ccc; } tr:nth-child(even) { background: #fff; } tr:nth-child(odd) { background: #37B8EB; color: #fff; } tr#header{ background: #37B8EB; } div#norecord{ margin-top:10px; width: 15%; margin-left: auto; margin-right: auto; } input,select{ cursor: pointer; } img{ margin-top: 10px; height: 200px; width: 300px; } select{ width: 200px } div.leftdiv{ width: 45%; padding: 0 10px; float: left; border: 1px solid #ccc; margin: 5px; height: 320px; text-align:center; } div.rightdiv{ width: 45%; padding: 0 10px; float: right; border: 1px solid #ccc; margin: 5px; height: 320px; text-align:center; } hidediv{ display: none; } p.header{ height: 40px; background-color: #37B8EB; color: #fff; text-align:center; margin: 0; margin-bottom: 10px; } textarea{ font-size: 25px; font-weight: bold; border: 2px solid #37B8EB; margin-bottom: 10px; text-align: center; padding: 10px; } button{ background-color: #37B8EB; border: 5px solid #37B8EB; padding: 10px; cursor: pointer; color: #fff; font-weight: bold; } </style> <script> function sendMsg(){ var msgLength = $.trim($("textarea").val()).length; var checkedCB = $("input[type='checkbox']:checked").length; if( checkedCB == 0){ alert("يجب عليك اختار جهاز واحد على الأقل لارسال له الرسالة"); }else if(msgLength == 0){ alert("الرجاء كتابة رسالة لارسالها, حقل الرسالة فارغ"); }else{ var formData = $(".wrapper").find("input").serialize() + "&imgurl="+ $("#festival").val() + "&message=" + $("textarea").val(); $.ajax({type: "POST",data: formData, url: "processmessage.php", success:function(res){ $(".greetblock").slideUp(1000); $(".serverresponse").prepend(res).hide().fadeIn(2000); }}); } } $(function(){ $(".serverresponse").hide() $("input[type='checkbox']").click(function(){ if($(this).is(':checked')){ $(this).parent().css("border","3px solid #008800"); }else{ $(this).parent().css("border","0px"); } }); $("div.leftdiv, div.rightdiv").hover(function(){ $(this).css("background","#FAFAFA"); },function(){ $(this).css("background","#fff"); }); $("#festival").change(function(){ $("img").attr("src",$(this).val()); }); $("#sendmsg").click(function(){ $(".serverresponse").fadeOut(300,function(){ $(".greetblock").fadeIn(1000); }); }); }); </script> </head> <body> <?php include_once 'db_functions.php'; $db = new DB_Functions(); $users = $db->getAllUsers(); if ($users != false) $no_of_users = mysql_num_rows($users); else $no_of_users = 0; ?> <?php if ($no_of_users > 0) { ?> <div class="greetblock"> <table border="1" width="100%" cellspacing="0" cellpadding="0"> <tr> <td bgcolor="#FFFFFF" align="center" valign="top"> <table width="100%"> <tr id="header"><td><?php echo $x = mysql_result(mysql_query("SELECT COUNT(id) FROM gcmusers "),0); ?></td><td>عدد الأجهزة المتصلة</td></tr> <?php while ($row = mysql_fetch_array($users)) { ?> <tr style="display:none"> <td><span><?php echo $row["id"] ?></span></td> <td><span class="wrapper"><input type="checkbox" name="sendmsg[]" value="<?php echo $row["id"] ?>" checked="selected"/></span></td> </tr> <?php } ?> </table> <p><b><font color="#37B8EB">BY: </font><a href="https://andrody.com/"> <font color="#37B8EB">AndRody.com</font></a></b></td><p> <td bgcolor="#FFFFFF"><p align="center"> <b><font size="5" color="#37B8EB">Test GCM - AndRoid - PHP - MySQL</font></b></p> <p> <textarea cols="45" rows="5" value="txtarea" placeholder="اكتب هنا رسالتك"></textarea></p> <p> <button onclick="sendMsg()">ارسال الرسالة</button></p> </td> </tr> </table> </div> <div class="serverresponse hidediv"> <center><button id="sendmsg">ارسال مرة اخرى</button></center> </div> <?php }else{ ?> <div id="norecord"> <font color="#37B8EB"><b>لا يوجد تسجيلات حتى الآن </b></font> </div> <?php } ?> </body> </html>
هكذا نكون أنتهينا من تجهيز السيرفر, والآن لننتقل لتجهيز تطبيق الاندرويد.
# تجهيز تطبيق الاندرويد :
الملفات المطلوبة منك إنشائها :
وقد تم شرحها في الدروس السابقة. وتقريباً نفسها تماماً لكن في هذا الدرس قمت باختصار أكواد كثيرة, ومع تستطيع الاختصار اكثر 🙂
نقوم بوضع الأكواد في الملفات السابقة كالتالي :
Home_Activity.java
package com.andrody.testandrody; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.os.AsyncTask; import android.os.Bundle; import android.text.TextUtils; import android.widget.TextView; import com.andrody.testgcm.Gcm_Application_Constants; import com.google.android.gms.gcm.GoogleCloudMessaging; import com.loopj.android.http.AsyncHttpClient; import com.loopj.android.http.AsyncHttpResponseHandler; import com.loopj.android.http.RequestParams; import java.io.IOException; /** * Created by Abboudi_Aliwi on 16/05/2015. */ public class Home_Activity extends Activity { RequestParams params = new RequestParams(); GoogleCloudMessaging gcmObj; String regId = ""; public static final String REG_ID = "regId"; TextView view_msg; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.home); // افتح الشيرد وخزن داخلها قيمة REG_ID SharedPreferences prefs = getSharedPreferences("UserDetails", Context.MODE_PRIVATE); String registrationId = prefs.getString(REG_ID, ""); // إذا كانت registrationId مخزنة سابقاً وموجودة وهي التي خزنت سابقاً قيمة REG_ID إذا كانت موجودة فلا تنفذ أي أمر if (!TextUtils.isEmpty(registrationId)) { } // إذا كانت غير موجودة قيمة registrationId فقم بتشغيل دالة تسجيل المستخدم من جديد لتخزين واحدة وهو معرف الاي دي else { registerInBackground();} // تعريف المسج وربطه بالاي دي view_msg = (TextView) findViewById(R.id.message); } // نهاية دالة الاون كريت public void onResume() { super.onResume(); // دالة يتم تنفيذها عند الرجوع لنفس الاكتفتي // افتح سترنج بإسم str وضع داخله قيمة msg وهي التي اتت من السيرفر String str = getIntent().getStringExtra("msg"); // سترنج فيه رسالة المسج التي أتت من السيرفر if (str != null) { view_msg.setText(str); // وضع رسالة المسج داخل الفيو مسج والذي هو النص المعروض للمستخدم } } // دالة التسجيل في حال المستخدم لم يكن مخزن تسجيل سابقاً private void registerInBackground() { new AsyncTask<Void, Void, String>() { @Override protected String doInBackground(Void... params) { String msg = ""; try { if (gcmObj == null) { gcmObj = GoogleCloudMessaging.getInstance(getApplicationContext()); } regId = gcmObj .register(Gcm_Application_Constants.GOOGLE_PROJ_ID); msg = "Registration ID :" + regId; } catch (IOException ex) { msg = "Error :" + ex.getMessage(); } return msg; } @Override protected void onPostExecute(String msg) { storeRegIdinSharedPref(getApplicationContext(), regId); } }.execute(null, null, null); } // تخزين الاي دي المسجل في جهاز المستخدم لكي لا يتم التسجيل مرة اخرى في حال الرجوع للتطبيق private void storeRegIdinSharedPref(Context context, String regId) { SharedPreferences prefs = getSharedPreferences("UserDetails", Context.MODE_PRIVATE); SharedPreferences.Editor editor = prefs.edit(); editor.putString(REG_ID, regId); editor.commit(); storeRegIdinServer(regId); } // تخزين الاي دي بقاعدة البيانات لاستخدامها في حال ارسال مسج للمستخدم private void storeRegIdinServer(String regId2) { params.put("regId", regId); // Make RESTful webservice call using AsyncHttpClient object AsyncHttpClient client = new AsyncHttpClient(); client.post(Gcm_Application_Constants.APP_SERVER_URL, params, new AsyncHttpResponseHandler() {}); } }
Gcm_Application_Constants.java
لا تنسى بتغيير رقم المشروع هنا والرابط كذلك حسب ما موجود لديك
package com.andrody.testgcm; /** * Created by Abboudi_Aliwi on 16/05/2015. */ public interface Gcm_Application_Constants { // رابط صفحة الربط مع السيرفر لتسجيل الاي دي static final String APP_SERVER_URL = "http://192.168.1.10/gcm/insertuser.php"; // غير الرابط حسب الموجود لديك // رقم المشروع على جوجل static final String GOOGLE_PROJ_ID = "71439801010"; // غير الرقم إلى رقم المشروع الذي أنشتئه // الرسالة التي تأتي من السيرفر static final String MSG_KEY = "m"; // }
Gcm_Broadcast_Receiver.java
package com.andrody.testgcm; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.support.v4.content.WakefulBroadcastReceiver; /** * Created by Abboudi_Aliwi on 16/05/2015. */ public class Gcm_Broadcast_Receiver extends WakefulBroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // Explicitly specify that GcmIntentService will handle the intent. ComponentName comp = new ComponentName(context.getPackageName(), Gcm_Notification_Intent_Service.class.getName()); // Start the service, keeping the device awake while it is launching. startWakefulService(context, (intent.setComponent(comp))); setResultCode(Activity.RESULT_OK); } }
Gcm_Notification_Intent_Service.java
package com.andrody.testgcm; import android.app.IntentService; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.support.v4.app.NotificationCompat; import com.andrody.testandrody.Home_Activity; import com.andrody.testandrody.R; import com.google.android.gms.gcm.GoogleCloudMessaging; /** * Created by Abboudi_Aliwi on 16/05/2015. */ public class Gcm_Notification_Intent_Service extends IntentService { // Sets an ID for the notification, so it can be updated public static final int notifyID = 9001; public Gcm_Notification_Intent_Service() { super("GcmIntentService"); } @Override protected void onHandleIntent(Intent intent) { Bundle extras = intent.getExtras(); GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this); String messageType = gcm.getMessageType(intent); if (!extras.isEmpty()) { if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR .equals(messageType)) { sendNotification("Send error: " + extras.toString()); } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED .equals(messageType)) { sendNotification("Deleted messages on server: " + extras.toString()); } else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE .equals(messageType)) { sendNotification("" + extras.get(Gcm_Application_Constants.MSG_KEY)); //When Message is received normally from GCM Cloud Server } } Gcm_Broadcast_Receiver.completeWakefulIntent(intent); } private void sendNotification(String msg) { Intent resultIntent = new Intent(this, Home_Activity.class); // بعد الضغط على الاشعار يذهب بنا الى اكتفتي هوم resultIntent.putExtra("msg", msg); // واثناء الذهاب الى اكتفتي هوم يأخذ معه الرسالة مخزنة داخل msg PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_ONE_SHOT); // لظهور الاشعار مرة واحدة بعد الضغط عليه يختفي NotificationCompat.Builder mNotifyBuilder; NotificationManager mNotificationManager; mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mNotifyBuilder = new NotificationCompat.Builder(this) .setContentTitle("رسالة جديدة") // عنوان الاشعار .setSmallIcon(R.mipmap.ic_launcher); // ايقونة الاشعار // Set pending intent mNotifyBuilder.setContentIntent(resultPendingIntent); // Set Vibrate, Sound and Light int defaults = 0; defaults = defaults | Notification.DEFAULT_LIGHTS; defaults = defaults | Notification.DEFAULT_VIBRATE; defaults = defaults | Notification.DEFAULT_SOUND; mNotifyBuilder.setDefaults(defaults); // تعيين محتوى الاشعار mNotifyBuilder.setContentText(msg); // يختفي الاشعار بعد الضغط عليه mNotifyBuilder.setAutoCancel(true); // اضافة الاشعار او بنائه mNotificationManager.notify(notifyID, mNotifyBuilder.build()); } }
بالنسبة للمبتدئين ” لا تنسى بتغيير اسم الحزمة كما موجود لديك ” , كما إن سطور التعليقات واضحة وكثيرة استعن بها, وشرح الملفات قد ذكر سابقاً في دروس سابقة.
home.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_centerInParent="true" android:background="#ff8b0000" android:gravity="center" android:orientation="vertical" android:padding="15dp" tools:context=".Home_Activity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="40dp" android:text="Welcome My Friend" android:textColor="#fff" android:textSize="25sp" android:textStyle="bold" /> <TextView android:id="@+id/message" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginBottom="10dp" android:background="#fff" android:hint="سوف تظهر هنا الرسالة التي سوف يتم ارسالها المبرمج من السيرفر" android:padding="10dp" android:textColor="#000" android:textSize="20dp" /> </LinearLayout>
أما بالنسبة لملف AndroidManifest.xml كذلك قد تم شرحه سابقاً, وهو كالتالي :
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.andrody.testandrody" android:installLocation="auto"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <permission android:name="com.andrody.testandrody.permission.C2D_MESSAGE" android:protectionLevel="signature" /> <uses-permission android:name="com.andrody.testandrody.permission.C2D_MESSAGE" /> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.VIBRATE" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme"> <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" /> <activity android:name=".Home_Activity" android:label="@string/app_name" android:noHistory="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name="com.andrody.testgcm.Gcm_Broadcast_Receiver" android:permission="com.google.android.c2dm.permission.SEND"> <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> <category android:name="com.andrody.testandrody" /> </intent-filter> </receiver> <service android:name="com.andrody.testgcm.Gcm_Notification_Intent_Service" /> </application> </manifest>
وهكذا نكون انتهينا من درس اليوم ,, كما أذكر أغلب الأكواد والملفات شرحت سابقاً ,, راجع الدروس السابقة في حال مواجهة أي مشكلة, وإذا لم تجد الحال تستطيع استخدام صندوق التعليقات بالأسفل لمساعدتك في حلها ..
بالنسبة لتطبيق الويب كما هو سابقاً ولكن هنا قد تم إضافة عدد المتصلين وهو عدد المضافين لقاعدة البيانات, وكذلك قمت بإخفاء العناصر المضافة وتحديدها بشكل تلقائي, في حال كان لديك خبرة بتطبيق الويب تستطيع تعديله كيف تريد وتظهر المضافين وتحديد لمن تريد الارسال لتحديد عدد معين ~
أختصرت درس اليوم لأن الأكواد مكررة معنا ولكن في كل درس يوجد هناك معلومات جديدة. أرجوا أن تكونوا قد استفدتم وانتظرونا في دروس جديدة وحصرية .. والسلام عليكم 🙂
اقترح اخي ان تقوم بإضافة سورس كود لكل تطبيق تقوم بعمل شرح عليه بصيغة zip لتعم الفائدة أكثر شكراً
تلقيت كثيراً هذا الاقتراح .. ولكن ما أريده هو أن تقوموا بكتابة الكود بنفسكم من أجل ان تعم الفائدة لكم ..
كما إن مشروع الاندرويد ستوديو ملفاته كثيرة .. وأغلب الشروحات لا تتعدى 3 اكتفتي – 3 لياوت .. وهكذا أثقل عليكم مشروع كامل من اجلها فقط ..
لكن أخي احياناً يتعذر علينا تنفيذ خطوات بشكل صحيح وتحصل أخطاء معنا أثناء كتابة الكود ويحصل تعليق في كمبيوتر مما يدفعنا إلى توقف عن برمجة تطبيق. يرجى ان تقوم برفعه بملف zip وخصوصاً للمبتدئين مثلي عندها استطيع دراسة تطبيق بهدوء دون الخوف من عمل أخطاء.
حسناً إن شاء الله من الدروس القادمة سوف يكون هناك تحميل للاوبن سورس كذلك في اقرب وقت فراغ سوف يتم اضافة الاوبن سورس للمواضيع السابقة.
اخى انا من متابع دروسك الجميله دى
بس نفسى تعمل حاجتين
الاول تشرح درس تعلمنا نصمم تطبيق فيه كذا زر
وكل زر ليه خصائص معينه من ضمنها فتح صفحة نت جوه التطبيق
ثانى حاجه انا دايخ قوى ومش عارف اعمل موضوع التنبيهات دى وبتطلعلى غلطات كتير
يا ترى ايه اللى ناقصنى هل المفروض احمل حاجات من ال sdk
ولا ايه بالظبط
ان شاء الله بالنسبة للدروس .. بإذن الله سوف اواصل هذا العمل .. لكن المشاريع تزداد عليي مع مرور الوقت ..
بالنسبة للتحميلات من الـ sdk , يجب تحميل خدمات جوجل بلاي .. وتفعيلها في مشروعك ..
راجع الدروس كاملة الخاصة بارسال الاشعارات .. وان شاء الله تجد جواباً لسؤالك 🙂
كيف افعل خدمات جوجل بلاي
طلبت منك مراجعة الدروس كاملة لتعرف كيفية تفعيلها في مشروعك ..
راجع التالي: https://andrody.com/2015/05/push_notifications_using_gcm_service_android/
great job thanks
Thanks
اخي أرجو منك المساعده , عندي أسبوع في نفس error 🙁
07-30 18:02:54.897 3966-3996/com.andrody.testandrody E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1
ممكن صورة من الخطأ ؟! … على الكود الذي فيه الخطأ ..
السلام عليك يا أخي عبد القادر شكرا على الإجابة, هاهي صورة من الخطأ
http://www.hostingpics.net/viewer.php?id=404852Capture.png
تمام اخي ..
ممكن تضغط على Home_Activity.java:62 لنرى موقع الخطأ من الكود لديك .. الخطأ بالتزامن مع الويب ..
ممكن صورة من الخطأ في الكود ..
أظن أنه من الازم إضافة مكتبات jar إلى emulator مثل google play service و أيضا إضافة account google في emulator. المشكل أني لم أستطع تحديد هذه المكتبات. أتمنى شرحا مفصل و جزاك الله خيرا ـ نزار من تونس
هذا code
http://www.hostingpics.net/viewer.php?id=745984Capture2.png
======= مشكلة سئلني عنها الكثير =======================
حسناً أخي انتا تستخدم المكتبة android-async-http-1.4.8.jar
وهناك أشياء كثيرة محدثة وينتج عن هذا تغيير الكود .. لذلك أخي الفاضل .. قم بتحميل النسخة 1.4.4 من هنا :
https://github.com/loopj/android-async-http/raw/master/releases/android-async-http-1.4.4.jar
وقم باستبدالها بالمكتبة .. ثم قم بنقل الكود من جديد الذي موجود بالدرس هنا ..
وبالتوفيق لك 🙂
شكرا أخي أرجو أني لم أزعجك بأسئلتي، للأسف مازال موجود نفس error
أريد أن أريك طريقة عملي و أنت قل لي هل أنا في الطريق الصحيح أم لا:
1: أضيف ملفات apk لل emulator لكي أستطيع أن أرى مشروعي و هم كلآتي :
com.google.android.gms-6.1.11+(1474901-038).apk
GoogleLoginService.apk
GoogleServicesFramework.apk
Phonesky.apk
2: أضيف account google لل emulator
3: أستعمل هذا code في Gcm_Application_Constants.java :
“static final String APP_SERVER_URL = “http://10.0.2.2:2356/gcm/insertuser.php
هل 10.0.2.2 adress IP for emulator صحيحة أم لا
أنتظر إجابتك أخي بفارغ الصبرأنا أعمل على gcm لأكثر من أسبوع، جربت العديد من الطرق و لم أفلح 🙁 و أرجو أن تكون إجابتك هي الحل و شكر
العفو , بالعكس اهلا وسهلا بك وارحب بجميع اسئلتك واستفساراتك 🙂
وجود نفس الخطأ , فأعتقد انك لم تتبع الدرس هذا بشرح مفصل من بدايته لنهايته ~
اخي الفاضل المحاكي لا يدعم خدمات جوجل بلاي لذلك لن يفيدك, وهذه الملفات ليس لها اي علاقة بالدرس , لذلك قم بعمل APK وتجربته على جوالك, او اعمل معاينة مباشرة من اندرويد ستوديو لجوالك.
بالنسبة لـ : 10.0.2.2 فهو حسب السيرفر لديك .. واعتقد فيه خطأ تأكد من اي بي جهازك من السيرفر الداخلي .. او رابط موقعك ..
شكرا لقد أحببت هذا لموقع لدروسكم الجيدة ، لإجاباتك السريعة و حسن أخلاقك
جازاك الله خيرا 🙂
العفو وهذا من ذوقك اخي الفاضل~ نورت موقعك 🙂
الله يعطيك الف عافية يارب
بس سؤال الخدمة محظورة بسوريا مافيني طبقها صح ؟
ربي يعاقيك خي ..
هلأ انا خارج سوريا .. بس دخلت بنقاش مع ناس جوات سورية, النتيجة انو بتشتغل بسورية لأنو
خدمات جوجل بتتفعل عن طريق مكاتب معينة , فإذا انتا وقت تدخل تطبيقات وتشوف اعلانات جوجل ظاهرة الك معناتو شغالة ..
والله اعلم .
هل ممكن مساعدة
اوجه مشكلة
Error:(98, 48) error: is not abstract and does not override abstract method onFailure(int,Header[],byte[],Throwable) in AsyncHttpResponseHandler
جزاك الله خير الجزاء ، حاولت كثيراً ولن لا يعمل التطبيق بالشكل المطلوب حيث انه لا يظهر أي مستخدمين في قاعدة البيانات و لا أعلم أين ممكن يكون الخطأ .. !
شكراً لك