ارسال الاشعارات لجميع مستخدمين التطبيق دون عملية تسجيل gcm – android

بسم الله الرحمن الرحيم

اليوم إن شاء الله رح نتعلم درس في كيفية ارسال اشعارات لجميع من يستخدم تطبيقك بواسطة سيرفر سحابة التراسل من جوجل gcm وهذا هو الدرس الرابع لنا في التعامل مع هذا السيرفر الضخم, ولنا دروس قادمة إن شاء الله فيه.

# راجع الدروس السابقة حول gcm :

  1. مقدمة لاستخدام GCM ببرمجة تطبيقات الاندرويد + تجهيزها
  2. ارسال الاشعارات في تطبيقات اندرويد برمجياً باستخدام GCM
  3. ارسال الاشعارات لاجهزة متعددة 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>

هكذا نكون أنتهينا من تجهيز السيرفر, والآن لننتقل لتجهيز تطبيق الاندرويد.

# تجهيز تطبيق الاندرويد :

الملفات المطلوبة منك إنشائها :Push_notifications_all_users_application_without_registering_gcm_android_1

وقد تم شرحها في الدروس السابقة. وتقريباً نفسها تماماً لكن في هذا الدرس قمت باختصار أكواد كثيرة, ومع تستطيع الاختصار اكثر 🙂

 

 

 

نقوم بوضع الأكواد في الملفات السابقة كالتالي :

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>

وهكذا نكون انتهينا من درس اليوم ,, كما أذكر أغلب الأكواد والملفات شرحت سابقاً ,, راجع الدروس السابقة في حال مواجهة أي مشكلة, وإذا لم تجد الحال تستطيع استخدام صندوق التعليقات بالأسفل لمساعدتك في حلها ..

بالنسبة لتطبيق الويب كما هو سابقاً ولكن هنا قد تم إضافة عدد المتصلين وهو عدد المضافين لقاعدة البيانات, وكذلك قمت بإخفاء العناصر المضافة وتحديدها بشكل تلقائي, في حال كان لديك خبرة بتطبيق الويب تستطيع تعديله كيف تريد وتظهر المضافين وتحديد لمن تريد الارسال لتحديد عدد معين ~

أختصرت درس اليوم لأن الأكواد مكررة معنا ولكن في كل درس يوجد هناك معلومات جديدة. أرجوا أن تكونوا قد استفدتم وانتظرونا في دروس جديدة وحصرية  .. والسلام عليكم 🙂

About عبدالقادر عليوي

مواليد 1996 , سوري الجنسية, طالب علم, لدي شغوف كبير في تعلم كل ما يتعلق بالانترنت من تطوير وحماية, أحب القراءة كثيراً .. هدفي نشر العلم بشتى أنواعه ومجالاته, متابع من الدرجة الأولى لـ الدكتور ابراهيم الفقي و الشيخ أحمد ديدات - رحمهم الله -.

Check Also

التقنيات التي نستطيع برمجة تطبيقات والعاب الاندرويد بها

هل أنت محتار من أين تريد البدأ في مجال برمجة التطبيقات للهواتف الذكية أو الألعاب عالية الاداء ؟ تعرف في هذا المقال عن اللغات والتقنيات واختر منها ما يناسبك لدخول هذا المجال

تعلم برمجة تطبيق اندرويد لمدونتك البلوجر (1)

هل لديك تدوينة أو موقع إخباري ؟ أو معرض يعرض الكثير من البيانات من وسائط ؟ وبحاجة لعرضها في تطبيق اندرويد ؟ هذه فرصتك من هنا وللمبتدئين تعلم برمجة تطبيق لمدونتك

عرض صورة في التطبيق من فايربيس

بسم الله الرحمن الرحيم اليوم سيكون شرحنا عن كيفية عرض صورة  في التطبيق من قاعدة …

26 comments

  1. اقترح اخي ان تقوم بإضافة سورس كود لكل تطبيق تقوم بعمل شرح عليه بصيغة zip لتعم الفائدة أكثر شكراً

    • تلقيت كثيراً هذا الاقتراح .. ولكن ما أريده هو أن تقوموا بكتابة الكود بنفسكم من أجل ان تعم الفائدة لكم ..
      كما إن مشروع الاندرويد ستوديو ملفاته كثيرة .. وأغلب الشروحات لا تتعدى 3 اكتفتي – 3 لياوت .. وهكذا أثقل عليكم مشروع كامل من اجلها فقط ..

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

        • حسناً إن شاء الله من الدروس القادمة سوف يكون هناك تحميل للاوبن سورس كذلك في اقرب وقت فراغ سوف يتم اضافة الاوبن سورس للمواضيع السابقة.

  2. اخى انا من متابع دروسك الجميله دى
    بس نفسى تعمل حاجتين
    الاول تشرح درس تعلمنا نصمم تطبيق فيه كذا زر
    وكل زر ليه خصائص معينه من ضمنها فتح صفحة نت جوه التطبيق

    ثانى حاجه انا دايخ قوى ومش عارف اعمل موضوع التنبيهات دى وبتطلعلى غلطات كتير
    يا ترى ايه اللى ناقصنى هل المفروض احمل حاجات من ال sdk

    ولا ايه بالظبط

    • ان شاء الله بالنسبة للدروس .. بإذن الله سوف اواصل هذا العمل .. لكن المشاريع تزداد عليي مع مرور الوقت ..

      بالنسبة للتحميلات من الـ sdk , يجب تحميل خدمات جوجل بلاي .. وتفعيلها في مشروعك ..

      راجع الدروس كاملة الخاصة بارسال الاشعارات .. وان شاء الله تجد جواباً لسؤالك 🙂

  3. كيف افعل خدمات جوجل بلاي

  4. great job thanks

  5. اخي أرجو منك المساعده , عندي أسبوع في نفس error 🙁

    07-30 18:02:54.897 3966-3996/com.andrody.testandrody E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1

  6. السلام عليك يا أخي عبد القادر شكرا على الإجابة, هاهي صورة من الخطأ
    http://www.hostingpics.net/viewer.php?id=404852Capture.png

    • تمام اخي ..

      ممكن تضغط على Home_Activity.java:62 لنرى موقع الخطأ من الكود لديك .. الخطأ بالتزامن مع الويب ..

      ممكن صورة من الخطأ في الكود ..

  7. أظن أنه من الازم إضافة مكتبات jar إلى emulator مثل google play service و أيضا إضافة account google في emulator. المشكل أني لم أستطع تحديد هذه المكتبات. أتمنى شرحا مفصل و جزاك الله خيرا ـ نزار من تونس

  8. شكرا أخي أرجو أني لم أزعجك بأسئلتي، للأسف مازال موجود نفس 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 فهو حسب السيرفر لديك .. واعتقد فيه خطأ تأكد من اي بي جهازك من السيرفر الداخلي .. او رابط موقعك ..

  9. شكرا لقد أحببت هذا لموقع لدروسكم الجيدة ، لإجاباتك السريعة و حسن أخلاقك
    جازاك الله خيرا 🙂

  10. الله يعطيك الف عافية يارب
    بس سؤال الخدمة محظورة بسوريا مافيني طبقها صح ؟

    • ربي يعاقيك خي ..

      هلأ انا خارج سوريا .. بس دخلت بنقاش مع ناس جوات سورية, النتيجة انو بتشتغل بسورية لأنو

      خدمات جوجل بتتفعل عن طريق مكاتب معينة , فإذا انتا وقت تدخل تطبيقات وتشوف اعلانات جوجل ظاهرة الك معناتو شغالة ..

      والله اعلم .

  11. هل ممكن مساعدة

  12. اوجه مشكلة
    Error:(98, 48) error: is not abstract and does not override abstract method onFailure(int,Header[],byte[],Throwable) in AsyncHttpResponseHandler

  13. جزاك الله خير الجزاء ، حاولت كثيراً ولن لا يعمل التطبيق بالشكل المطلوب حيث انه لا يظهر أي مستخدمين في قاعدة البيانات و لا أعلم أين ممكن يكون الخطأ .. !

    شكراً لك

ضع بصمتك بتعليق يعبر عن امتنانك

هذا الموقع يستخدم Akismet للحدّ من التعليقات المزعجة والغير مرغوبة. تعرّف على كيفية معالجة بيانات تعليقك.